首先是Thread类的源码:
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal源码:
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();
}
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和get时,实际上是对一个ThreadLocalMap进行操作,
而这个ThreadLocalMap对象是使用当前线程对象传递给getMap方法得到的一个map对象。而getMap方法是怎么拿到当前线程的ThreadLocalMap对象呢?
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。
初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。
然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。
总结:ThreadLocal对象 实际上是对当前线程的ThreadLocalMap对象引用的一个封装(副本),ThreadLocal对象的set和get方法,实质上是对当前线程对象的ThreadLocalMap的set和get方法。