网上有许多关于 ThreadLocal 的文章,读了很多,总感觉他们说的 ThreadLocal 造成内存泄露的理由很牵强,今天就看源码彻底解析一下 ThreadLocal。
源码就不放了,直接放梳理好的类和对象的引用图。
下面对这张图做下解释
大方框代表堆里的对象,里面蓝色的小方框代表该对象的成员变量。实线代表强引用,虚线代表弱引用。
那么我们先不考虑场景,根据这张图,ThreadLocal 发生内存泄露的唯一可能性是什么?
ThreadLocalMap 里面的元素发生爆炸式增长切无法被释放。
那么什么情况下会有大量不同的 ThreadLocalMap 的 key?
当这个 key 是方法内部临时创建的 ThreadLocal 的本地变量的时候。
那么 ThreadLocal 变量可能出现在哪些地方(上图的某个强引用)?
方法的本地变量,对象的成员变量,类的静态变量。
如果 ThreadLocal 变量是一个方法静态变量会造成内存泄露吗?
不会,因为无论什么情况下,ThreadLocalMap 里的 key 都只有一个。
如果 ThreadLocal 变量是一个对象的成员变量会造成内存泄露吗?
该对象是单例不会,是多例且频繁创建和回收的就会。
那么如何保持 ThreadLocalMap 本身一直被强引用不被释放掉呢?
只要当前线程一直不退出,那么该线程的 ThreadLocalMap 就一直不会被释放。
什么情况下当前线程一直不退出呢?
使用线程池的时候。
好了,对于 ThreadLocal 什么情况下会造成内存泄露的分析就到此完毕了。
总结:当使用线程池,且 ThreadLocal 为一个频繁调用方法的本地变量,且使用后没有调用 ThreadLocal 的 remove 方法的时候。
对了,忘了说 ThreadLocal 的 remove 方法了,它只是将当前线程的 ThreadLocalMap 里 key 为当前方法的 ThreadLocal 的本地变量的 entry 给 remove 了,这样就不会造成内存泄露了。