ThreadLocal原理及使用场景

一、ThreadLocal原理

要了解ThreadLocal得先从Thread类说起,从Thread类源码可以看出,每个Thread都有个threadLocals变量。

public
class Thread implements Runnable {
    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;
    }

了解了Thread类后再理解ThreadLocal则简单多了,ThreadLocal的set和get操作其实就是对Thread的threadLocals变量进行操作。

package java.lang;
import java.lang.ref.*;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

public class ThreadLocal<T> {

    /**
     * Returns the value in the current thread's copy of this
     * thread-local variable.  If the variable has no value for the
     * current thread, it is first initialized to the value returned
     * by an invocation of the {@link #initialValue} method.
     *
     * @return the current thread's value of this thread-local
     */
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

   
    /**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
	ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
}
/**
     * Create the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the map
     */
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
二、使用场景

当一个参数并不是每个方法都需要时,可以使用ThreadLocal进行参数传递。
代码示例

public class TokenUtils {
    private final static ThreadLocal<String> tokenContext = new ThreadLocal<>();

    public static void setToken(String regionId) {
        tokenContext.set(regionId);
    }

    public static String getToken() {
        return tokenContext.get();
    }
}
### Java `ThreadLocal` 工作原理 `ThreadLocal` 是一种特殊的变量容器,允许每个线程拥有该变量的一个独立副本。这意味着不同线程之间无法相互干扰彼此持有的 `ThreadLocal` 变量实例[^1]。 具体来说,在 JVM 中每一个线程都维护着一个名为 `ThreadLocalMap` 的哈希表结构来保存这些特定于当前线程的数据项。每当调用 `set()` 方法向某个 `ThreadLocal` 对象赋值时,实际上是在对应的线程内部创建了一个键值对记录;当通过 `get()` 获取值的时候,则是从这个映射关系里查找并返回相应的对象引用[^2]。 对于继承自父级线程属性的情况(即 `InheritableThreadLocal`),JVM 还会复制一份来自父进程的相关配置给新启动的孩子们使用[^3]。 ```java public class ThreadLocalExample { private static final ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0); public void increment() { Integer value = threadLocalValue.get(); threadLocalValue.set(value + 1); } public int getValue() { return threadLocalValue.get(); } } ``` 这段代码展示了如何定义一个初始值为零 (`withInitial`) 的整数类型的 `ThreadLocal` 实例,并实现了两个方法用于操作其上的数值——增加计数器(`increment`) 和读取当前值(`getValue`)。 ### 应用场景 #### 数据库连接池管理 在一个典型的Web应用服务器环境中,多个请求可能并发执行数据库查询任务。为了提高性能和资源利用率,通常采用连接池技术预先分配一定数量的数据库链接供后续重用。此时就可以利用 `ThreadLocal` 来确保每次HTTP请求处理过程中所使用的都是同一个持久化的Session对象,从而简化事务管理和错误恢复逻辑[^4]。 #### 用户上下文传递 假设存在一个多租户SaaS平台架构下的微服务组件通信链路,其中涉及到跨层传播认证信息的需求。借助 `ThreadLocal` ,可以在进入业务流程之初就将登录用户的唯一标识符存入内存空间内,之后无论经过多少次函数调用跳转都不会丢失这条重要线索,直到整个交易结束为止自动清除掉临时缓存的内容。 #### 并发计算中的状态保持 考虑这样一个例子:有一个复杂的算法需要分成若干个小部分由不同的工作单元协同完成。如果希望各个子任务能够共享某些中间结果而不必担心同步竞争条件带来的麻烦的话,那么完全可以把它们封装成静态字段形式并通过 `ThreadLocal` 方式来进行分发控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值