1. 首页
  2. 编程面试题
  3. Java
  4. 并发多线程

ThreadLocal 内存泄漏的原因及如何避免



内存泄露为程序在申请内存后,无法释放已申请的内存空间,- -次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

**不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露。**

**强引用:**使用最普遍的引用(new), -个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。

如果想取消强引|用和某个对象之间的关联,可以显式地将引用赋值为null,这样可以使JVM在合适的时间就会回收该对象。

**弱引用:** JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中, 用java.lang.re.WeakReference类来表示。可以在缓存中使用弱引用。

ThreadLocal 的实现原理,每一个Thread维护一个ThreadlocalMap ,key为使用弱引用的ThreadLocal实例,value为线程变量的副本。

ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部**强引用**时,Key(ThreadLocal)势必会被GC回收,这样就会导致ThreadLocalMap中key为null,而value还存在着强引用, 只有thead线程退出以后,value的强引用链条才会断掉,但如果当前线程再迟迟不结束的话,这些key为nul的Entry的value就会一直存在一 条强引用链(红色链条)

key使用强引用

当hreadLocalMap的key为强弓l用回收ThreadLocal时,因为ThreadLocalMap还持有 ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收, 导致Entry内存泄漏。

key使用弱引用

当ThreadLocalMap的key为弱弓l用回收ThreadLocal时,由于ThreadLocalMap持有 ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。 当key为null, 在下一-次ThreadLocalMap调用set),get(), remove(方法的时候会被清除value值。

因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread-样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。

ThreadLocal正确的使用方法

- 每次使用完ThreadLocal都调用它的remove()方法清除数据
- 将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用, 也就能保证任何时候都能通过ThreadLocal的弱引|用访问到Entry的value值,进而清除掉。

发布者:admin,如若转载,请注明出处:https://ai1024.vip/39728.html

QR code
//