1.前言
之前一直听说ThreadLocal
会出现内存泄露的情况,也看过相关文章,看的时候大概知道为什么会出现内存泄露,过一段时候后就会忘记内存泄露的根源在哪。为了彻底搞懂此问题,于是就有了此篇文章。
2.线程Thread
要想弄清ThreadLocal
,就不得不提Thread
。Thread
中持有ThreadLocalMap
引用,ThreadLocalMap
的key
引用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 thread
到CurrentThread
引用就会断开,GC
后CurrentThread
就会被回收,该情况下不会发生内存泄露 - 当使用完
ThreadLocal
后调用remove()
方法也不会发生内存泄露
4. 总结
使用ThreadLocal
要想不发生内存泄露,要么确保线程不被循环使用,要么显示调用其remove()
方法,推荐在使用完后显示调用remove()