1.为什么key要设置成弱引用呢?
先来看看ThreadLocalMap对 key和value的构造:
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
在set方法中,会将key和value以entry对象进行存储,key就是我们的ThreadLocal引用,value就是我们要设置的值。
Entry这个类继承了WeakReference类,并且在构造方法中,将key设置成了弱引用,而value则是强引用。
也就是说,在这个Entry里,key,也就是ThreadLocal对象时被这个entry弱引用的,val是被这个entry强引用的。
如果外界没有变量引用ThreadLocal对象时,它是只有entry里的这个弱引用的;这也就达成了当没有人引用某个ThreadLocal对象时,这个对象就应该被回收掉的目的。
ThreadLocalMap是和线程绑定在一起的,如果这个线程没有被销毁,而某个ThreadLocal又不会被引用了,那么key-value键值对就会一直在map中存在。这对于程序来说,就出现了内存泄漏。
为了避免这种情况,只要将key设置为弱引用,那么当发生GC的时候,就会自动将弱引用给清理掉,也就是说,假如某个用户A执行方法时产生了一份threadlocalA,然后再很长一段时间都用不到threadlocalA时,作为弱引用,它会在下次垃圾回收时被清理掉。
而且ThreadLocalMap再内部的set,get和扩容时都会清理掉泄漏的Entry,内存泄漏完全没必要过于担心。
2. 那value为什么不设置成弱引用呢?ThreadLocalMap不是持有对这个value的强引用,它还会被回收吗?
如果value是弱引用,而key(threadlocal)变量为某个类的成员变量时,key在线程运行期间都是强引用的,而value在下次gc就被回收掉了。那么就可能出现通过key获取value时,拿到null值的情况。