1.为阅读体验,本站无任何广告,也无任何盈利方法,站长一直在用爱发电,现濒临倒闭,希望有能力的同学能帮忙分担服务器成本
2.捐助10元及以上同学,可添加站长微信lurenzhang888,备注捐助,网站倒闭后可联系站长领取本站pdf内容
3.若网站能存活下来,后续将会持续更新内容
要搞懂
ThreadLocal的底层原理需要看下他的源码,太长了,有兴趣的同学可以自己看看相关资料,这里只是简单介绍下结构,因为Threadlocal内存泄露是个高频知识点,并且需要简单了解ThreadLocal结构。
ThreadLocal的原理可以概括为下图:

从上图可以看出每个线程都有一个ThreadLocalMap,ThreadLocalMap中保存着所有的ThreadLocal,而ThreadLocal本身只是一个引用本身并不保存值,值都是保存在ThreadLocalMap中的,其中ThreadLocal为ThreadLocalMap中的key。其中图中的虚线表示弱引用。
这里简单说下Java中的引用类型,Java的引用类型主要分为强引用、软引用、弱引用和虚引用。
- 强引用:发生 gc 的时候不会被回收。
- 软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。
- 弱引用:有用但不是必须的对象,在下一次GC时会被回收。
- 虚引用:无法通过虚引用获得对象,虚引用的用途是在 gc 时返回一个通知。
为什么ThreadLocal会发生内存泄漏呢?
因为ThreadLocal中的key是弱引用,而value是强引用。当ThreadLocal没有被强引用时,在进行垃圾回收时,key会被清理掉,而value不会被清理掉,这时如果不做任何处理,value将永远不会被回收,产生内存泄漏。
如何解决ThreadLocal的内存泄漏?
其实在ThreadLocal在设计的时候已经考虑到了这种情况,在调用set()、get()、remove()等方法时就会清理掉key为null的记录,所以在使用完ThreadLocal后最好手动调用remove()方法。
为什么要将key设计成ThreadLocal的弱引用?
如果ThreadLocal的key是强引用,同样会发生内存泄漏的。如果ThreadLocal的key是强引用,引用的ThreadLocal 的对象被回收了,但是ThreadLocalMap 还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,发生内存泄漏。
如果是弱引用的话,引用的ThreadLocal的对象被回收了,即使没有手动删除,ThreadLocal也会被回收。value也会在ThreadLocalMap调用 set()、get()、remove() 的时候会被清除。
所以两种方案比较下来,还是ThreadLoacl的key为弱引用好一些。
本站链接:https://www.mianshi.online,如需勘误或投稿,请联系微信:lurenzhang888
点击面试手册,获取本站面试手册PDF完整版