ThreadLocal原理
- ThreadLocal是Java中所提供的线程本地存储机制,可以利⽤该机制将数据缓存在某个线程内部,成为线程内的局部变量
- 该线程可以在任意时刻、任意⽅法中获取缓存的数据
- 这样每个线程都自己管理自己的局部变量,别的线程操作的数据不会产生影响,互不影响
- 一般使用ThreadLocal,官方建议定义为private static
- ThreadLocal底层是通过ThreadLocalMap来实现的,每个Thread对象(注意不是ThreadLocal对 象)中都存在⼀个ThreadLocalMap,Map的key为ThreadLocal对象,Map的value为需要缓存的 值
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
- 其中2为弱引用
ThreadLocal内存泄漏问题
- 内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果
- 不当使用ThreadLocal可能会导致内存泄漏
- 因为当ThreadLocal对象使⽤完之后,应该要 把设置的key,value,也就是Entry对象进⾏回收
- 如果线程长期没有结束(如线程池中的核心线程),线程对象是通过 强引⽤指向ThreadLocalMap,ThreadLocalMap也是通过强引⽤指向Entry对象,线程不被回收, Entry对象也就不会被回收,从⽽出现内存泄漏
- 解决办法:在使⽤了ThreadLocal对象之后,手动调⽤ThreadLocal的remove⽅法,手动清除Entry对象
ThreadLocal内存泄漏模拟
过程剖析
- 在网上查阅了大量的文章,发现将ThreadLocal原理的文章一抓一大把,而且内容千篇一律,但却鲜有将内存泄漏现象模拟出来的。
- 因此,本文的重点是对ThreadLocal内存泄漏现象的模拟,但原理是模拟的前提,因此还是提前介绍了原理。
- 定义一个类继承Thread,并重写run方法,run方法里编写模拟逻辑:为threadlocal对象赋值 —》将threadlocal对象置空—》调用System.gc()手动进行垃圾回收—》观察前后 Thread对象中 ThreadLocalMap的变化
public class TestForThreadLocal {
ThreadLocal