Thread类中有一个threadLocals变量,类型为ThreadLocalMap
public class Thread {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
ThreadLocalMap对key的引用是弱引用,对value的引用是强引用。
假设我们在一个方法内定义了一个ThreadLocal局部变量,在方法运行过程中,这个ThreadLocal变量同时持有2个引用:
- java虚拟机栈的局部变量表对ThreadLocal变量的强引用
- ThreadLocalMap对ThreadLocal变量的弱引用
单条引用链的可达性以最弱的引用类型决定,多条引用链的可达性以最强的引用类型决定,因此方法运行过程中,ThreadLocal变量拥有强引用,不会被垃圾回收。
当方法运行结束后,ThreadLocal变量仅剩ThreadLocalMap对它的虚引用,随时可能被垃圾回收掉。
当ThreadLocal对象被回收之后,ThreadLocalMap里key为null,value不为null,但是只要Thread类还在运行,ThreadLocalMap对value的强引用就有效,因此value不会被自动回收。
因此,当我们使用完ThreadLocal之后,需要手动remove掉,remove方法里会把value设置为null。
为什么ThreadLocaMap对value的引用不做成弱引用?
- key,除了ThreadLocaMap的弱引用,可能还会有ThreadLocal的强引用(方法还没运行结束时),只要后者还在,Key就不会被回收。
- value只有ThreadLocaMap的引用,如果value是弱引用,那随时会被回收,ThreadLocal就没法用了。