前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Java] ThreadLocalMap.Entry的Key是弱引用的理解

[Java] ThreadLocalMap.Entry的Key是弱引用的理解

原创
作者头像
用户3702315
修改2021-04-07 14:40:37
1.3K1
修改2021-04-07 14:40:37
举报
文章被收录于专栏:安卓开发
图解
BSCSYV.jpg
BSCSYV.jpg
ThreadLocalMap
代码语言:txt
复制
static class ThreadLocalMap {
    private Entry[] table;
}
Entry
代码语言:txt
复制
static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal k, Object v) {
        super(k);
        value = v;
    }
}
解读
代码语言:txt
复制
// 示例场景
new Thread(){
    public void run(){
	    func1();
    }

    // 新建了一个 ThreadLocal 对象,t1 是强引用指向这个对象
    // 调用 set() 后,新建一个 Entry 对象,key 弱引用指向这个对象
    public void func1() {
        ThreadLocal tl = new ThreadLocal<Integer>();
        tl.set(100);
        tl.get();
    }
}
BSCct0.png
BSCct0.png
笔记
  1. 当 func1() 执行完毕后,栈帧销毁,强引用 tl 也就没有了,但此时线程的ThreadLocalMap里某个entry的 k 引用还指向这个对象。若这个k 引用是强引用,就会导致k指向的ThreadLocal对象及v指向的对象不能被gc回收,造成内存泄漏,但是弱引用就不会有这个问题。使用弱引用,在Entry的key引用为null后,就可以使ThreadLocal对象在方法执行完毕后顺利被回收。
  2. 线程池这样的环境,线程结束没有销毁回收,那么value永远不会被回收,当存在大量这样的value的时候,就会产生内存泄漏,那么Java 8中是通过调用ThreadLocal的get、set或remove方法时,就会尝试删除所在线程的ThreadLocalMap中key为null的Entry,可以释放value对象所占用的内存。
  3. 虽然弱引用,保证了k指向的ThreadLocal对象能被及时回收,但是v指向的value对象是需要ThreadLocalMap调用get、set时发现 key 为null时才会去回收整个Entry,因此弱引用不能保证内存完全不泄露。
笔记

我们要在不使用某个 ThreadLocal 对象后,手动调用 remoev 方法来删除它,尤其是在线程池中,不仅仅是内存泄露的问题,因为线程池中的线程是重复使用的,意味着这个线程的 ThreadLocalMap 对象也是重复使用的,如果我们不手动调用 remove 方法,那么后面的线程就有可能获取到上个线程遗留下来的 value 值,造成 bug。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 图解
  • ThreadLocalMap
  • Entry
  • 解读
  • 笔记
  • 笔记
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档