使用ThreadLocal时需注意,一定要及时调用remove()方法清楚ThreadLocal,否则会发送内存泄漏,最终导致内存溢出
ThreadLocal的原理:每个Thread类有个ThreadLocalMap,而ThreadLocal本身并不存储数据,使用ThreadLocalMap来存储(相当于Map的功能,只不过它存储用的Entry节点而不是Entry链表),这个ThreadLocalMap的key是ThreadLocal对象本身,value就是要存储的value。
ThreadLocal内存泄漏的原因:基于上面的原理,分析下内存泄漏的原因。因为ThreadLocalMap的生命周期和当前线程Thread是一样的(通过源码可知:t.threadLocals = new ThreadLocalMap(this, firstValue);),而ThreadLocalMap的key是ThreadLocal,他们之间弱引用(见源码:static class Entry extends WeakReference<ThreadLocal> {
/** The value associated with this ThreadLocal. */),所以当ThreadLocal被回收的时候,ThreadLocalMap的key就为null了,对应的value找不到了,导致了内存泄漏。jdk也有些保障措施,在我们调用set()、get()的时候,会清楚key为null的数据,但是这样被动清楚也不能完全避免内存泄漏。
扩展:为什么用弱引用而不用强引用,其实这也是jdk的保障措施,因为如果是强引用,那么ThreadLocal也不能被回收,会造成更大的内存浪费。