ThreadLocal 中的 Entry 为什么要继承WeakRefrence<ThreadLocal>

ThreadLocalMap 的 Entry 继承了 WeakRefrence<ThreadLocal>。
为什么这样子?
有人说是为了防止内存泄漏,但是没有给出怎样情况下会发生内存泄漏。
有木有大神可以详细分析一下WeakRefrence的作用,还有Entry为什么要继承WeakRefrence。

继承一个WeakRefrence 又是什么个意思?

阅读 2.4k
2 个回答

ThreadLocal是为线程中的对象服务的。ThreadLocalMap中保存的是当前线程中的ThreadLocal对象所引用的其他对象。

ThreadLocal对象不再使用的时候,最好把它从ThreadLocalMap中的Entry对象中删掉,以免引起内存泄露。WeakRefrence正好适合这种场景。

比如有下面这个对象:

public class Foo {
    private ThreadLocal tl = ...

    ......
}

Foo对象中的tl不再使用的时候,应该让垃圾回收器把tl回收掉。但是如果不使用WeakRefrence,那么当前线程上的ThreadLocalMap中就会有一个Entry引用着tl对象,导致垃圾回收器无法回收tl,除非线程结束,这样就存在内存泄露的风险。

将实体中的ThreadLocal对象通过WeakRefrence来引用,当tl对象不再使用的时候,WeakRefrence中的引用会自动断开,这样就不会阻止垃圾回收了。

看一个例子

        for (int i = 0; i < 10; i++) {
            byte[] buff = new byte[1024 * 1024];
            WeakReference<byte[]> sr = new WeakReference<>(buff);
            list.add(sr);
        }
        
        System.gc(); //主动通知垃圾回收
        
        for(int i=0; i < list.size(); i++){
            Object obj = ((WeakReference) list.get(i)).get();
            System.out.println(obj);
        }
}
这里的list持有WeakReference,接下来还会get,也就是还会使用,还是被全部回收了。
再来看一个例子
       List<WeakReference<byte[]>> list=new ArrayList<>();
       List<byte[]> list1=new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            byte[] buff = new byte[1024 * 1024];
            //也就是说回收了WeakReference的部分
            list1.add(buff);
            WeakReference<byte[]> sr = new WeakReference<>(buff);
            list.add(sr);
        }

        System.gc(); //主动通知垃圾回收

        for(int i=0; i < list.size(); i++){
            Object obj = ((WeakReference) list.get(i)).get();
            System.out.println(obj);
        }
这次的没有被回收,也就说,我们的threadlocal强引用还在的时候,不会被回收,但是当threadlocal使用完了以后,就只剩下Entry对象的引用,这种场景就很适合用弱引用
推荐问题
宣传栏