ThreadLocal是否会导致内存泄露
什么是内存泄露?
维基百科的定义:【内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存】,我的理解就是程序失去了对某段内存的控制,那么这段内存就算是泄露了。
ThreadLocal为什么会导致内存泄露?
关于讲ThreadLocal实现原理的: http://ifeve.com/%E4%BD%BF%E7%94%A8threadlocal%E4%B8%8D%E5%BD%93%E5%8F%AF%E8%83%BD%E4%BC%9A%E5%AF%BC%E8%87%B4%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2/
关于将Reference的: https://my.oschina.net/robinyao/blog/829983
从上面的文章我理解ThreadLocal的内存泄露可能性比较小,但是有,场景是在一个线程里给ThreadLocal放了一个非常大的对象,然后取消所有对ThreadLocal的强引用。 这样这个对象占用的内存在这个线程消亡前是访问不到的。
最初使用ThreadLocal的时候理解是每个线程独享这里面存放的变量,这个理解是没有问题的,但是要注意在线程池场景下,一个线程会重复使用,这样就可能出现一个请求会访问到上次请求的数据。
模拟的代码:
public class Test { private static ThreadLocal<Long> threadLocal = new ThreadLocal<>(); public static void main(String[] args){ threadLocal.set(10l); ExecutorService pool = Executors.newFixedThreadPool(1); for(int i = 0; i < 10; i ++){ pool.submit(new Runnable() { @Override public void run() { threadLocal.set(1L); System.out.println(threadLocal.get()); } }); } } }
在main线程里设置的10不会打印出来,但是在线程池中设置的这个1会一直打印出来,因为这个线程池我设置的线程数是1,也就是多个任务都会在一个线程中执行,前一个任务设置的1后面的任务也可以访问到。
2021-08-11补充:
ThreadLocalMap:
容量默认16,达到75%扩容一倍,使用线性探测解决hash冲突。
key为ThreadLocal对象,且key作为WeakReference,所以如果ThreadLocal没有直接引用的话,ThreadLocalMap里的key会被回收掉,防止key的内存泄露
在执行get/set时清理掉key为null的元素。
remove指定清理。