1、threadLocal用于解决何种问题?

threadLocal是给每个线程开辟一个副本,各自的线程可以独立操作副本内的变量而互不干扰。

那么由此可以知道,threadLocal并不是用来解决线程间需要共享数据的问题,因为对于共享数据的修改,线程各自仍然修改各自的,并没有起到同步作用。

threadLocal解决的问题是可以由各自线程独立使用的变量,为了不受线程间互相干扰而提出的方案,例如session、simpleTimeStamp等

2、threadLocal原理

threadLocal底层维护了一个threadLocalMap,用于存储线程引用及线程变量,key为每个线程的引用,value为线程变量object,其提供了get、set以及remove方法用于操作,同样是key,value键值对存储,与hashMap等不同的是,当key发生冲突时,hashMap采用链表+红黑树解决,而这里采用寻址方式解决,即冲突时会继续寻找下一个可使用的存储位

3、threadLocal内存泄漏由来

可以注意到,threadLocalMap存储时,并不都是使用强引用方式,key采用了弱引用,而value是强引用,弱引用的对象将会在GC时被回收无论内存是否足够,这意味着当key的引用被回收后,若value仍然保持着强引用,那么该引用的存在将会导致内存泄漏,因为已经无法通过key找到value。

那么何种情况下会导致这种问题的发生呢,例如使用线程池执行任务时,即使任务已经执行完毕,由于池化保活机制并不会销毁线程,这就导致value强引用存在不会正常被GC回收,其存在着引用关系Thread->ThreadLocalMap->Entry->value。

本质上threadLocal内存泄漏是由于key被回收时,其value未被正确回收所导致的。

4、threadLocal如何避免内存泄漏

(1)尽量避免在长生命周期中使用threadLocal

(2)虽然threadLocal本身的get、set、remove方法的调用都会自动清除key为null的value,但仍然有风险,故而在使用完threadLocal时最好主动调用remove方法进行清除