ThreadLocal
要点
ThreadLocal是线程独有的,线程之间隔离。
ThreadLocal在整个线程上下文中都可以获得,可以避免参数的反复传递。
ThreadLocal在用完之后要通过finally清除,否则如果线程复用,会遗留到下一次处理中。
get()
1 public T get() { 2 Thread t = Thread.currentThread(); 3 ThreadLocalMap map = getMap(t); 4 if (map != null) { 5 ThreadLocalMap.Entry e = map.getEntry(this); 6 if (e != null) { 7 @SuppressWarnings("unchecked") 8 T result = (T)e.value; 9 return result; 10 } 11 } 12 return setInitialValue(); 13 }
首先获得当前线程的threadLocals变量(getMap(t)),这个变量的类型是ThreadLocal.ThreadLocalMap,可以看作是一个map,存储着该线程所有ThreadLocal对象。
接下来判断如果map不为空,则拿到map中所需的ThreadLocalMap.Entry(它是ThreadLocal弱引用的子类),如果Entry也不为空,则返回Entry的value,即实际存储的对象。
如果两次判断有一个失败了,则调用setInitialValue()进行初始化。
小结
可以看出来,ThreadLocal和ThreadLocal.ThreadLocalMap.Entry其实是对应关系,而中间经过了一个ThreadLocal.ThreadLocalMap的类似map的对象。
ThreadLocal的精妙之处
1.ThreadLocal通过每个线程独立的ThreadLocalMap变量,实现了每个线程的Entry的独立。
2.经过这个ThreadLocalMap变量后,ThreadLocal实际转换为其弱引用类型的子类Entry,可以实现每个Entry的自动清理:每个Entry随着被get,被强引用,而当线程销毁后,只剩下弱引用,Entry便会随着下次GC被清理掉。
3.ThreadLocalMap底层是用一个Entry数组存放Entry对象的,因为如果是Map形式存放会涉及到Node指针的问题,会存在强引用,不便于GC自动清理。

浙公网安备 33010602011771号