Skip to content

ThreadLocalUtils

java
/**
 * 一个线程安全的 ThreadLocal 工具类。
 * 注意:在使用线程池的场景下(如Web服务器),
 * 必须在请求处理完成后调用 removeAll() 方法,以防内存泄漏。
 */
@SuppressWarnings("unchecked")
public abstract class ThreadLocalUtils {

    private ThreadLocalUtils() {
    }

    // 使用 <String, Object> 是一种更常见的实践,可以增加类型安全性和可读性
    private static final ThreadLocal<Map<String, Object>> THREAD_LOCAL = ThreadLocal.withInitial(HashMap::new);

    /**
     * 获取当前线程的 ThreadLocal Map。
     *
     * @return 当前线程的 Map 实例。
     */
    public static Map<String, Object> getThreadLocalMap() {
        return THREAD_LOCAL.get();
    }

    /**
     * 从当前线程的 Map 中获取一个值。
     *
     * @param key
     * @param <T> 值的类型
     * @return 键对应的值,如果不存在则返回 null
     */
    public static <T> T getValue(String key) {
        // 每次都从 ThreadLocal 获取当前线程的 Map
        return (T) THREAD_LOCAL.get().get(key);
    }

    /**
     * 从当前线程的 Map 中获取一个值,如果不存在则返回默认值。
     *
     * @param key
     * @param defaultValue 默认值
     * @param <T> 值的类型
     * @return 键对应的值,或默认值
     */
    public static <T> T getValueOrDefault(String key, T defaultValue) {
        Object value = getValue(key);
        return value == null ? defaultValue : (T) value;
    }

    /**
     * 向当前线程的 Map 中设置一个键值对。
     *
     * @param key
     * @param value
     */
    public static void setValue(String key, Object value) {
        THREAD_LOCAL.get().put(key, value);
    }

    /**
     * 将一个 Map 中的所有键值对设置到当前线程的 Map 中。
     *
     * @param sourceMap 源 Map
     */
    public static void setAll(Map<String, Object> sourceMap) {
        THREAD_LOCAL.get().putAll(sourceMap);
    }

    /**
     * 从当前线程的 Map 中移除一个键值对。
     *
     * @param key 要移除的键
     */
    public static void remove(String key) {
        THREAD_LOCAL.get().remove(key);
    }

    /** 清空当前线程 Map 中的所有键值对。 Map 对象本身依然存在,只是变为空了。 */
    public static void clear() {
        THREAD_LOCAL.get().clear();
    }

    /**
     * 移除当前线程的整个 Map 实例。 这是防止内存泄漏的最佳实践。调用后,当前线程的 ThreadLocal 就干净了。 下次再调用 get()
     * 会重新创建一个新的空 Map。
     */
    public static void removeAll() {
        THREAD_LOCAL.remove();
    }
}

Released under the MIT License.