之前的一个评论,博主把文章删除了。
ThreadLocal内部的ThreadLocalMap键为弱引用,会有内存泄漏的风险,真的是这样吗?
我认为不太合理。原因是:
-
ThreadLocalMap中的Entry弱引用(key)到的是 threadLocal 对象,
此处的弱引用意图是,当外界不再持有对 threadLocal 对象的强引用的时候,
threadLocal 对象可以被GC。此处Entry对 threadLocal 的弱引用不会引起内存泄露。 -
Entry除了持有对threadLocal的弱引用之外还持有对value的强引用。
先说为什么调用了threadLocal.remove() 就解决了内存泄漏的风险。
threadLocal.remove() 这个方法最终会有机会执行到:
entry.value = null;
entry = null;
这样就解除了entry对value的强引用关系,当外部也没有对value的强引用的时候,
value就可以被GC。
如果不调用threadLocal.remove() 这个方法,其实也是要分情况来考虑的。
我们知道 entry 是被 threadLocalMap 引用的;而 threadLocalMap 是被 thread 引用的。
如果一个thread执行完毕,进入 TERMINATED 状态时,作为一种GC Root,
terminated 状态的 thread本身就是可以被GC的。
那么thread所引用的 threadLocalMap 也就是可以被GC的。
那么什么情况下 threadLocalMap 不能被回收呢?
那就是thread并不会进入 terminated 状态的时候。
什么时候不进入 terminated 呢?就是当 thread 配合线程池使用的情况下,thread在运行完毕之后
会被再次放回线程池。
那么如果这个线程永远不被用到,此处的threadLocalMap 包括entry 和 entry引用的value 就不能被回收了。
那么如果这个线程被再次启用,那么threadLocalMap也就不会再重新初始化了。
此处应该考虑另外一个问题,那就是如果再次调用 threadLocal.get() 方法,得到的是上一次set的内容,
也就是脏读了。
网友评论