就内存泄露聊聊ThreadLocal

418 阅读1分钟

1.前言

之前一直听说ThreadLocal会出现内存泄露的情况,也看过相关文章,看的时候大概知道为什么会出现内存泄露,过一段时候后就会忘记内存泄露的根源在哪。为了彻底搞懂此问题,于是就有了此篇文章。

2.线程Thread

要想弄清ThreadLocal,就不得不提ThreadThread中持有ThreadLocalMap引用,ThreadLocalMapkey引用ThreadLocal,value为使用者设置的值。

3.ThreadLocal

3.1 ThreadLocal使用示例代码

public class ThreadLocalUtils {
​
    private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
​
    public static void set(Integer value) {
        threadLocal.set(value);
    }
​
    public static Integer get() {
        return Objects.nonNull(threadLocal.get()) ? threadLocal.get() : null;
    }
​
    public static void remove() {
        threadLocal.remove();
    }
}

3.2 内存图

有了示例代码,又有了内存图,下面就来分析分析ThreadLocal为什么会出现内存泄露

3.3 内存泄露场景

当线程循环使用(线程池),CurrentThread就不会被回收,假如Entry中的value占用比较大的内存空间,就会发生内存泄露

3.4 安全场景

  • 当方法执行完成后线程得到释放,Thread threadCurrentThread引用就会断开,GCCurrentThread就会被回收,该情况下不会发生内存泄露
  • 当使用完ThreadLocal后调用remove()方法也不会发生内存泄露

4. 总结

使用ThreadLocal要想不发生内存泄露,要么确保线程不被循环使用,要么显示调用其remove()方法,推荐在使用完后显示调用remove()