【Java面试】说说你对ThreadLocal内存泄漏问题的理解
创始人
2024-03-25 06:19:04
0

文章目录

  • 前置知识
  • 为什么会产生内存泄漏问题?
  • 如何解决内存泄露问题?
  • 为什么要使用弱引用?

前置知识

讲解ThreadLocal的内存泄漏问题之前,首先得先知道什么是内存泄漏。
Memory overflow:内存溢出,没有足够的内存提供申请者使用。
Memory leak:内存泄漏是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。内存泄漏的堆积终将导致内存溢出。

一文讲清强软弱虚四种引用类型

为什么会产生内存泄漏问题?

下面是大致的结构图,在栈中存放当前线程对象的引用以及ThreadLocal的引用。
他们指向了堆中的对象实例。
我们知道ThreadLocalMap(下文统称为Map)中的Entry的key使用的是ThreadLocal对象。
那么如果这里是一个强引用,那么如果我们设置ThreadLocal的引用为null,那么此时由于Map中的的Entry强引用了ThreadLocal作为键,因此此时会造成ThreadLocal无法被回收,在没有手动删除这个Entry或者当前线程仍然在运行的情况下,始终有强引用链 Thread的引用-》Thread对象-》Map-》Entry-》Key(ThreadLocal)和value-》内存。 此时就造成了内存泄漏。
因此如果ThreadLocalMap中的key使用了强引用,是完全无法避免内存泄漏的。
在这里插入图片描述
那么我们知道,ThreadLocalMap中的Entry继承了一个弱引用。也就是情况如下:
在这里插入图片描述
和上面不同的地方在于,在ThreadLocal的引用被回收之后,没有任何一个强引用指向ThreadLocal对象了,那么此时ThreadLocal就会被gc回收。因此此时Entry中的key为null。
但是,在没有手动删除这个Entry以及当前线程依旧运行的情况下,还是存在强引用链
Thread的引用-》Thread对象-》Map-》Entry-》Key(null)和value-》内存,value依旧不会被回收,而且这块value永远不会被访问到了,导致内存泄漏。
也就是说即使使用了弱引用,还是会导致内存泄漏。

如何解决内存泄露问题?

你可能很疑惑,都已经使用了弱引用了,为什么还是内存泄漏啊?
因为弱引用本身就不是为了解决这个问题而使用的。那么内存泄漏的真正原因是说明?
其实无非两个原因:

  • Entry没有被删除
  • 外部线程依旧在运行

第一点好理解,只要在使用完毕ThreadLocal之后调用remove方法删除Entry就可以避免内存泄漏。
第二点比较复杂,由于ThreadLocalMap是Thread的一个属性,并且被当前线程所引用,他的生命周期和Thread一样长,那么在使用完毕ThreadLocal的时候,Thread也随之结束,那么ThreadLocalMap自然也会被gc回收,也就从根源上避免了内存泄漏问题。
综上,内存泄露问题的根源是:由于ThreadLocalMap的生命周期和Thread一样长,如果没有手动删除对应数据,而只是把ThreadLocal设定为空,就会导致内存泄漏。

为什么要使用弱引用?

根据刚才的分析我们知道了:无论ThreadLocalMap中的key使用哪种类型引用都无法完全避免内存泄漏,跟使用弱引用没有关系。
要避免内存泄漏有两种方式:

  • 使用完ThreadLocal,调用其remove方法删除对应的Entry
  • 使用完ThreadLocal,当前Thread也随之运行结束

相对第一种方式,第二种方式显然更不好控制,特别是使用线程池的时候,线程结束是不会销毁的。
也就是说,只要记得在使用完ThreadLocal及时的调用remove,无论key是强引用还是弱引用都不会有问题。
那么为什么key要用弱引用呢?
事实上,在ThreadLocalMap中的set/getEntry方法中,会对key为null (也即是ThreadLocal为null )进行判断,如果为null的话,那么是会对value置为null的。
这就意味着使用完ThreadLocal , 当前线程依然运行的前提下,就算忘记调用remove方法,弱引用比强引可以多一层保障∶弱引用的ThreadLocal会被回收,对应的value在下一次ThreadLocalMap调用set,get,remove中的任一方法的时候会被清除,从而避免内存泄漏。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...