ThreadLocal内存泄漏分析
ThreadLocal是什么?来,百度百科
ThreadLocal是Thread的局部变量,用于编多线程程序,对解决多线程程序的并发问题有一定的启示作用。
ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,也许把它命名为ThreadLocalVariable更容易让人理解一些。
就是一个当前线程私有的保存一些当前线程内共享变量的一个东西。可以用来保存用户信息(我这样搞的,也不知道对不对)以及跨很多方法,在spring拦截器中通过解析JWT获得用户信息,然后调用service查找完整用户,最后保存到ThreadLocal中,在所有完成后再清除
好了,进入正题
先来段源码:
public class Thread implements Runnable {
.......
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
.......
可以看到在Thread类里面有一个 ThreadLocal.ThreadLocalMap 类型的threadLocals一看是很多threadlocal嘛。这里贴上马士兵老师的图
【图不知道怎么传】
可以看到threadlocal的存储方式,将自己作为key,存储的值作为value放在map中,这里再来看一下源码
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
这里的super(k)的意思是调用父类的构造函数,而父类是啥呢,显而易见是WeakReference是弱引用,弱引用有个特点就是只要发生垃圾回收,它所指向的对象就会被回收。那为啥threadlocal没有被回收呢,其实还有个强引用指向他,这样就保证了不会被回收,那为啥不把key也设置成强引用,但是呢,图片上也说了,如过说将tl=null的话。这个对象会被回收吗,显然是不可能的,因为key也是强应用嘛,属于gc root,肯定不可能被回收。但是外部又访问不到,这不就造成内存泄漏了。所以说被设置为弱引用,但是这样就不会发生内存泄露了吗?
不是的,依然会发生,假设将tl=null,因为key是弱引用,所以只要发生垃圾回收就会被jvm回收,这样的话value的值怎么访问?k都没了还有v啥事,有人会说了,线程被回收了不就好了,是的。但是现在基本上都是使用线程池,线程还会被回收吗。所以说,依然会发生内存泄漏,所以在使用完threadlocal后要记得调用remove方法移除。
本文来自博客园,作者:小鸡小鸡快点跑,转载请注明原文链接:https://www.cnblogs.com/clion/p/14105335.html

浙公网安备 33010602011771号