Java知识点----ThreadLocal杂记

这篇博客深入探讨了ThreadLocal的工作原理及其可能导致的内存泄漏问题。ThreadLocal通过弱引用连接ThreadLocal对象和Thread,但强引用的value可能导致内存泄漏。在线程池环境中,未手动移除ThreadLocal可能导致value在ThreadLocalMap中永久驻留,引发内存泄漏。解决办法是在使用完ThreadLocal后,及时调用remove方法清理数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

ThreadLocal

ThreadLocal实际是操作ThreadLocalMap的入口,只有传递参数的作用,并不会直接持有数据,真正存储数据的是其静态内部类ThreadLocalMap,ThreadLocal的属性包括当前线程和要保存的值,ThreadLocal只是提供set/get方法,通过ThreadLocal将Thread赋给ThreadLocalMap的key,想要保存的值赋给ThreadLocalMap的value,所以一个ThreadLocal=一个Thread=一个要保存的值=全局ThreadLocalMap中的key,在使用线程池的情况下,线程会被复用,这时候虽然对应的ThreadLocal回收了,但是其中ThreadLocalMap中作为key的Thread依然存在,并且不会被回收,最终导致内存泄露

 

一个ThreadLocal对应一个ThreadLocalMap对应一个Entry数组对应一个Thread;

一个Thread对应一个ThreadLocalMap对应一个Entry数组对应多个ThreadLocal;

 

ThreadLocal底层用一个静态内部类ThreadLocalMap存数据,这个ThreadLocalMap底层是一个Entry,这个Entry又继承自  WeakReference<ThreadLocal<?>>。线程与value之间有存在Thread.threadLocals = ThreadLocalMap的关系,所以Entry里面的Key指向ThreadLocal的引用是一个弱引用,目的是为了防止内存泄漏,Value是强引用。

Q:为什么key是弱引用,而不是强引用?

A:如果key是强引用,即使将ThreadLocal的对象设置为null,因为还存在Thread.threadLocals = ThreadLocalMap的强引用关系,所以ThreadLocal对象在Thread生命周期内不会被GC回收。而弱引用即使因为发生GC,导致ThreadLocal的对象被回收,只要还在同一个Thread生命周期内再次使用ThreadLocal时,也能通过Thread.currentThread()再次获取到Thread对象,通过Thread.threadLocals获取到ThreadLocalMap,从而再次建立ThreadLocal到Thread的关系。

Q:为什么value是强引用,而不设置成弱引用呢?

A:弱引用在GC时会被回收,Thread中通过ThreadLocalMap暂存的数据会丢失,这样即使ThreadLocal再次重建了ThreadLocal到Thread的关系,其中最重要的value也不存在了。所以只能是强引用,在Thread线程结束时,线程被回收,ThreadLocalMap也跟着回收。

Q:为什么会发生内存泄漏?
虽然弱引用解决了key,也就是线程的ThreadLocal能及时被回收,但是value却依然存在内存泄漏的问题。因为存在一条Thread.threadLocals = ThreadLocalMap的强引用关系。ThreadLocalMap里面的value不会被回收.而这块value永远不会被访问到了. 所以存在着内存泄露,

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

在线程池中存在着线程复用的情况,因为Thread.threadLocals对应的是一个Map结构,也就是说可以有多个ThreadLocal对应同一个Thread, 那么Key对应的Value因为Thread没有结束,所以仍然没有被回收,从而发生内存泄漏(所以很清楚发生内存泄漏并不是因为弱引用)。避免这种情况的方式是每次使用完ThreadLocal,手动调用它的remove方法,清除数据。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值