ThreadLocal
的引用在jvm中如下图:
因为CurrentThreadRef -> CurrentThread -> Map -> Entry
该引用链是强引用,所以Entry的生命周期与线程一致。所以只要线程存活,GC
就不可能把Entry
回收,造成内存泄露。
如何避免内存泄露
由图中的引用链可知,只要线程还存活,就一定会有内存泄露的问题。因此避免泄露的方法一:
使用完ThreadLocal
,当前Thread
也随之运行结束。
还有一种更直接的方法二:
使用完ThreadLocal
,调用其remove
方法删除对应的Entry
为什么使用弱引用
首先,java
的弱引用(WeakReference
),在发生GC
时,无论内存是否足够,都会进行垃圾回收。
当ThreadLocal
使用完毕之后,Entry
的Key
便被回收变为null
。在ThreadLocalMap
中的set/getEntry
方法中,会对key
为null
(也即是ThreadLocal
为null
)进行判断,如果为null
的话,那么是会对value
置为null
的。
这就意味着使用完ThreadLocal
,CurrentThread
依然运行的前提下,就算忘记调用remove
方法,弱引用比强引用可以多一层保障:弱引用的ThreadLocal
会被回收,对应的value
在下一次ThreadLocalMap
调用set,get,remove
中的任一方法的时候会被清除,从而避免内存泄漏。