ThreadLocal内部结构

1
2
3
4
5
6
7
8
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

当调用 ThreadLocal 的 set 方法检查当前线程线程的 threadLocals 的是否被初始了,如果没有则调用 createMap 进行初始化。

然后将 ThreadLocal 变量当做 key, set 到线程的 threadLocals 这个Map中。

所以每一个线程 new 的 ThreadLocal 都是与其所在的线程有关的。这样就做到了线程安全。

当调用 ThreadLocal 的 get 方法时: 就从当前线程的 Map 中以 ThreadLocal 对象作为 key 来获取其所对应的 value.

线程的 threadLocals 变量

1
2
3
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

// get 过程初始化
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}

private T setInitialValue() {
// 调用 initialValue 获得初始值
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
// 初始化 Thread.threadLocals
createMap(t, value);
return value;
}

// set 过程初始化
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
// 初始化 Thread.threadLocals
createMap(t, value);
}

由 setInitialValue 的实现可知,可以通过 继承类 ThreadLocal 并 override 其 initialValue 方法,给这个 ThreadLocal 提供一个初始值。这样,如果 ThreadLocal 变量在没有调用 set 的前提下,调用 get 方法时这个 初始值将被 set 到 Map 中,同时由 get 返回。

对 null 的支持

由 ThreadLocal.ThreadLocalMap.set 方法的实现可知,对于 value 是支持 null 值的。

所以,下面的调用

1
tLocal.set(null);

将以 <tLocal, null> 键值对存储到当前线程的 Map 中。