ThreadLocal为什么要使用弱引用和内存泄露问题

在threadlocal的生命周期中,都存在这些引用. 看下图: 实线代表强引用,虚线代表弱引用.
在这里插入图片描述

1.为什么要使用弱引用

每个thread中都存在一个map, map的类型是ThreadLocal.ThreadLocalMap.

Map中的key为一个threadlocal实例. 这个Map的确使用了弱引用,不过弱引用只是针对key.

每个key都弱引用指向threadlocal.

所以当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal就可以顺利被gc回收

注意!假如每个key都强引用指向threadlocal,也就是上图虚线那里是个强引用,那么这个threadlocal就会因为和entry存在强引用无法被回收!造成内存泄漏 ,除非线程结束,线程被回收了,map也跟着回收。

如果 key 是强引用,那么发生 GC 时 ThreadLocalMap 还持有 ThreadLocal 的强引用,会导致 ThreadLocal 不会被回收,从而导致内存泄漏。弱引用 ThreadLocal 不会内存泄漏,对应的 value 在下一次 ThreadLocalMap 调用 set、get、remove 方法时被清除,这算是最优的解决方案。

2.依然出现的内存泄露问题

虽然上述的弱引用解决了key,也就是线程的ThreadLocal能及时被回收,但是value却依然存在内存泄漏的问题。

当把threadlocal实例置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收.

map里面的value却没有被回收.而这块value永远不会被访问到了. 所以存在着内存泄露,

因为存在一条从current thread连接过来的强引用.

只有当前thread结束以后, current thread就不会存在栈中,强引用断开, Current Thread, Map, value将全部被GC回收.

3.总结

JVM利用设置ThreadLocalMap的Key为弱引用,来避免内存泄露。
JVM利用调用remove、get、set方法的时候,回收弱引用。

当ThreadLocal存储很多Key为null的Entry的时候,而不再去调用remove、get、set方法,那么将导致内存泄漏。

当使用static ThreadLocal的时候,延长ThreadLocal的生命周期,那也可能导致内存泄漏。因为,static变量在类未加载的时候,它就已经加载,当线程结束的时候,static变量不一定会回收。那么,比起普通成员变量使用的时候才加载,static的生命周期加长将更容易导致内存泄漏危机

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

熊猫-IT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值