总体介绍:
ThreadLocal 是 Java 中的一个类,用于提供线程局部变量,即每个线程都有自己独立的变量副本。即使在一个类中定义了静态的 ThreadLocal 对象,每个线程在访问这个 ThreadLocal 对象时,实际上访问的是各自线程内部的独立副本,而不是共享的实例。
ThreadLocal 的工作原理是这样的:
- 当一个线程首次访问 ThreadLocal 对象的 get() 或 set() 方法时,ThreadLocal
会为该线程创建一个独立的变量副本。 - 这个副本存储在每个线程自己的 ThreadLocalMap 中,ThreadLocalMap 是 Thread 类的一个成员变量。
- ThreadLocalMap 是一个特殊的哈希表,它的键是 ThreadLocal 对象本身,值是线程局部变量的副本。
- 当线程调用 ThreadLocal 的 get() 方法时,ThreadLocal 会查找该线程的
ThreadLocalMap,并返回与当前 ThreadLocal 对象关联的值。 - 当线程调用 ThreadLocal 的 set() 方法时,ThreadLocal 会更新该线程的 ThreadLocalMap 中与当前 ThreadLocal 对象关联的值。
- 相关源码如下:
/* ThreadLocalMap 是 Thread 类的一个成员变量。
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/** set方法源码
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 initialValue method to set the values of thread-locals.
Params:
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); // 后续获取都是当前线程自身的 threadLocals 对象
if (map != null)
map.set(this, value);
else
createMap(t, value); // 通过它进行初始化
/** get 方法源码
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 initialValue method.
Returns: the current thread's value of this thread-local */
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); // 后续获取都是线程自身的 ThreadLocalMap
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue(); // 设置一个默认值 null
/** 初始化线程本地的ThreadLocalMap 源码
* 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);
}
/** 获得当前线程对象的自己独有的 ThreadLocalMap 对象
* Get the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @return the map
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
/** ThreadLocalMap 构造方法源码(map结构得出每个ThreadLocal对象只能对应一个值)
* Construct a new map initially containing (firstKey, firstValue).
* ThreadLocalMaps are constructed lazily, so we only create
* one when we have at least one entry to put in it.
*/
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY]; // 初始容量-必须是2的幂。默认 16
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
总结:
ThreadLocal 的设计目的是为每个线程提供一个独立的变量副本,以便每个线程可以独立地修改自己的副本而不影响其他线程。因此,ThreadLocal 的 set() 方法只会更新当前线程的 ThreadLocalMap 中对应的值,而不是添加多个值。