ThreadLocal内存泄漏的缘故
2021/10/24 7:11:30
本文主要是介绍ThreadLocal内存泄漏的缘故,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
我们通常会用ThreadLocal用来存储当前线程的数据。但是在实际使用的时候注意使用完之后及时调用实例的remove方法。
他把数据绑定到当前线程代码原理是这么干的。
首先Thread类里面存储ThreadLocalMap。
然后ThreadLocalMap是ThreadLocal的内部类。
可以看到ThreadLocalMap里面entry是以ThreadLocal作为key值的。
他存储数据到当前线程是这么干的。
相当于ThreadLocal本身不存储数据,而是作为key放在其内部类ThreadLocalMap中,数据作为value放在ThreadLocalMap中。
要取数据的时候。通过当前线程获取其ThreadLocalMap,然后根据threadlocal实例获取对应的数据。
从上面可以看出,ThreadLocalMap是里面entry是以ThreadLocal作为key值的,而且还是弱引用的。意味着下次gc的时候,不管jvm堆内存是否足够,threadlocal都会被回收掉,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法回收,造成内存泄漏。
我们复现一下ThreadLocal内存泄漏的现象。
public class Test { public static void main(String[] args) { new Thread(() -> { // ThreadLocal放置到代码块中,为证明threadLocal 会被GC回收掉 { ThreadLocalTest<ValueVO> threadLocal = new ThreadLocalTest<>(); threadLocal.set(new ValueVO()); System.out.println(threadLocal.get()); } int i = 0; while (true) { try { Thread.sleep(1000); //每秒加10M 堆内存 能看出内存增长趋势 //GC时,a临时变量会被回收 int[] a = new int[1024 * 1024 * 10]; if (i++ > 100) { break; } i++; } catch (InterruptedException e) { } } }).start(); } } class ValueVO { @Override public String toString() { return "hello,world"; } @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("value deading"); } } /** * 继承ThreadLocal,实现finalize方法,垃圾回收器准备释放内存的时候,会先调用finalize()。 * * @param <T> */ class ThreadLocalTest<T> extends ThreadLocal<T> { @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("key deading"); } }
然后发现ThreadLocalMap的作为key值的ThreadLocal被垃圾回收了,作为value的当前线程的ValueVo的数据最后都没被回收。
解决办法:每次使用完ThreadLocal,都调用它的remove()方法,清除数据。
这篇关于ThreadLocal内存泄漏的缘故的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-15PingCAP 黄东旭参与 CCF 秀湖会议,共探开源教育未来
- 2024-05-13PingCAP 戴涛:构建面向未来的金融核心系统
- 2024-05-09flutter3.x_macos桌面os实战
- 2024-05-09Rust中的并发性:Sync 和 Send Traits
- 2024-05-08使用Ollama和OpenWebUI在CPU上玩转Meta Llama3-8B
- 2024-05-08完工标准(DoD)与验收条件(AC)究竟有什么不同?
- 2024-05-084万 star 的 NocoDB 在 sealos 上一键起,轻松把数据库编程智能表格
- 2024-05-08Mac 版Stable Diffusion WebUI的安装
- 2024-05-08解锁CodeGeeX智能问答中3项独有的隐藏技能
- 2024-05-08RAG算法优化+新增代码仓库支持,CodeGeeX的@repo功能效果提升