为什么 ThreadLocal 会导致内存泄漏 ?如何解决 ?

面试官问 :为什么 ThreadLocal 会导致内存泄漏 ??

在面试中被问到这个问题,如果记不清细节了,可以这样回答:

        ThreadLocal 里面存储的数据,它的生命周期是和线程或者线程池的生命周期保持一致的,如果在整个程序的运行期间,线程和线程池都没有销毁的情况下,那么 ThreadLocal 里面的数据也不会被销毁,也不会被垃圾回收器所回收,这个就是内存泄露问题。当程序中有大量的数据,并且 ThreadLocal 里面所记录的都是大数据的情况下,那么持续的内存泄漏就有可能会造成内存溢出(OutOfMemory)。

ThreadLocal 导致内存泄漏问题的细节分析 :

        Thread 源码中,每个线程 Thread 都拥有一个数据存储存储容器 ThreadLocalMap,在执行 ThreadLocal.set 方法的时候,会将存储的值放到 ThreadLocalMap 容器中ThreadLocalMap 中有一个 Entry[] 数组用来存储所有的数据,此处的 Entry[] 可以理解为哈希桶。

它们之间的引用关系是这样的:

Thread -> ThreadLocalMap -> Entry -> key,Value

        当线程池没有被销毁的时候,线程池也会一直持有 value 值,那么垃圾回收器就无法回收 value,所以就会持续不断的内存泄漏,从而导致内存溢出!!

为什么是一直持有 value ?

因为 ThreadLocal 在设计的时候,Entry 中的 key 使用的是弱引用,而 value 使用的是强引用

        如果 ThreadLocal 没有被直接引用(外部强引用),那么在垃圾回收的时候,由于 ThreadLocalMap 中的 key 是弱引用,所以 key 一定会被回收,因此 ThreadLocalMap 中就会出现 key 为 null 的 Entry,并且没有办法访问这些数据,那么强引用链 Thread -> ThreadLocalMap -> Entry -> value 就会一直存在,导致 value 无法被 GC 回收,从而导致内存泄漏。

【补充】

引用类型分为 4 种 :强引用、软引用、弱引用、虚引用(几乎不用)

  • 强引用无法被 GC 回收
  • 软引用一般不会被 GC 回收,除非内存不够用了,触发了 full GC 了,那么才可能会回收软引用。
  • 弱引用会被 GC 回收

为什么 ThreadLocal 在设计的时候,Entry 中的 key 使用弱引用,value 使用强引用 ?

我的个人理解:这是从 ThreadLocal 的性能和防止内存溢出这两方面综合考量的,如果说程序后面还需要使用 ThreadLocalMap,那么当插入的键值对的 value 已经存在时,就不需要重新进行插入了,只需要恢复当前键值对的 key 即可。

如何解决 ThreadLocal 内存泄漏问题 ??

只需要在使用完 ThreadLocal 之后,调用它的 remove 方法就可以避免内存泄漏问题了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Master_hl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值