ThreadLocal为什么会出现内存泄漏,你真的知道吗?

原文链接:ThreadLocal为什么会出现内存泄漏,你真的知道吗? – 编程屋

目录

1 前言

2 ThreadLocal进行线程隔离的小示例

3 原因

1 前言

大家想要搞清楚这个问题,就必须知道内存泄漏和内存溢出的区别

内存泄漏:不就被使用的对象或者变量无法被回收

内存溢出:没有剩余的空间来创建新的对象

2 ThreadLocal进行线程隔离的小示例

同一个threadlocal对象,不同线程之间存储的值是获取不到的

public class QuThreadLocal {

  static ThreadLocal t1 =  new ThreadLocal<>();

    public static void main(String[] args) {
        new Thread(()->{
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t1.set(new Wolf("小王"));
            System.out.println(t1.get());
            t1.remove();
        }).start();


        new Thread(()->{
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(t1.get());
        }).start();
    }
}

控制台输出: 

ThreadLocal为什么会出现内存泄漏,你真的知道吗?_第1张图片

 可以发现在不同的线程里面放置东西,其它线程里面是找不到的。

解析原因,观察是如何向threadlocal中放置值的:

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

1)先获取当前线程t,然后根据t获取threadmap对象

2)判断map是否为null,map不为null时,将当前threadllocal对象作为key,想要设置的值作为value放置其中,否则就创建一个map。创建map的key值与上相同。

这也表明了,存储的值只有当前线程才能够获取到。

3 原因

threadlocal内部结构:

ThreadLocal为什么会出现内存泄漏,你真的知道吗?_第2张图片

造成内存泄漏的原因:

        由于Entry中的value是强引用,key是弱引用;当垃圾回收器回收threadlocal时,由于value是强引用,不能被回收,所以造成了内存泄漏。

        因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应的key就会导致内存泄漏,而并不是因为弱引用。

解决方案一:扩大成员变量Threadlocal的一个作用域,避免被GC回收(不推荐)

解决方案二:每次使用完threadlocal之后,就调用remove方法去移除对应的数据(推荐)

以上只是部分内容,为了维护方便,本文已迁移到新地址:ThreadLocal为什么会出现内存泄漏,你真的知道吗? – 编程屋

你可能感兴趣的:(多线程,java,servlet,jvm)