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指定清理。

posted @ 2019-03-12 18:12  Birding  阅读(797)  评论(0编辑  收藏  举报