ThreadLocal - 内存泄露

本文探讨了ThreadLocal内存泄漏的两种情况:强引用导致的对象不被回收,以及弱引用如何影响内存释放。核心在于理解ThreadLocalMap的生命周期和清理策略,强调及时移除Entry以防止内存泄漏。
摘要由CSDN通过智能技术生成

目录

1.内存泄漏

2.假设 key=ThreadLocal被强引用

3. key=ThreadLocal被弱引用

4. 内存泄漏的真实原因

5. 为什么key要被弱引用


1.内存泄漏

  • 内存溢出: Memory overflow 没有足够的内存提供申请者使用.
  • 内存泄漏: Memory Leak 程序中已经动态分配的堆内存由于某种原因, 程序未释放或者无法释放, 造成系统内部的浪费, 导致程序运行速度减缓甚至系统崩溃等严重结果. 内存泄漏的堆积终将导致内存溢出

源码:ThreadLocal - 基础_java threadlocal创建数据库-CSDN博客

2.假设堆中的ThreadLocal对象被Entry强引用

在这里插入图片描述

  • 假设在业务代码中使用完ThreadLocal, ThreadLocal ref被回收了
  • 但是因为threadLocalMap的Entry强引用了threadLocal(key就是threadLocal), 造成ThreadLocal无法被回收
  • 在没有手动删除Entry以及CurrentThread(当前线程)依然运行的前提下, 始终有强引用链CurrentThread Ref → CurrentThread →Map(ThreadLocalMap)-> entry, Entry就不会被回收( Entry中包括了ThreadLocal实例和value), 导致Entry内存泄漏

3. 实际上堆中的ThreadLocal对象被Entry弱引用

  • 假设在业务代码中使用完ThreadLocal, ThreadLocal ref被回收了
  • 由于threadLocalMap只持有ThreadLocal的弱引用, 没有任何强引用指向threadlocal实例(这里Entry不再强引用ThreadLocal了), 所以threadlocal就可以顺利被gc回收, 此时Entry中的key = null
  • 在没有手动删除Entry以及CurrentThread依然运行的前提下, 也存在始终有强引用链CurrentThread Ref → CurrentThread →Map(ThreadLocalMap)-> entry,value就不会被回收, 而这块value永远不会被访问到了(因为key=null), 导致value内存泄漏。

4. 内存泄漏的真实原因

在这里插入图片描述

比较以上两种情况,我们就会发现:
内存泄漏的发生跟 ThreadLocalIMap 中的 key 是否被弱引用是没有关系的。

ThreadLocal 内存泄漏的根因是:

  • 由于ThreadLocalMap 的生命周期跟当前 Thread 一样长,在当前Thread结束之前,如果没有手动删除对应的Entry(手动调用remove()方法)就会导致内存泄漏。

​ 要避免内存泄漏有两种方式:

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

相对第一种方式,第二种方式显然更不好控制,特别是使用线程池的时候,线程结束是不会销毁的。也就是说,只要记得在使用完ThreadLocal 及时的调用 remove ,无论 key 是强引用还是弱引用都不会有问题。

5. 为什么key要被弱引用

  • 事实上,在 ThreadLocalMap 中的set/getEntry 方法中,会对 key 为 null(也即是 ThreadLocal 为 null )进行判断,如果为 null 的话,那么会把 value 置为 null 的。
  • ​这就意味着使用完 ThreadLocal , 在CurrentThread 依然运行的前提下,如果忘记手动调用 remove 方法,那么被弱引用会比被强引用多一层保障:被弱引用的 ThreadLocal 会被回收,对应value在下一次 ThreadLocaIMap 调用 set/get/remove 中的任一方法的时候会被清除,从而避免内存泄漏。
     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值