ThreadLocal源码解读及内存泄漏

ThreadLocal

ThreadLocal是什么?

从名字可以看出ThreadLocal叫做线程本地,即ThreadLocal中填充的变量是属于当前线程的,该变量对其它线程而言是隔离的

源码分析一下ThreadLocal的作用

ThreadLocal<M> tl = new ThreadLocal<>();
tl.set(new M());
tl.remove();

点进去set()方法看一下:

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

获取当前线程,然后将ThreadLocal作为key,你设置的值作为value,放到了一个ThreadLocalMap中.

我们再看一下createMap()方法:

很简单,就是new了一个ThreadLoaclMap

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

再看一下getMap()方法:

注意,getMap()方法是在Thread类当中,维护了ThreadLocalMap变量ThreadLocal.ThreadLocalMap threadLocals = null;

即每一个线程内部都有一个ThreadLocalMap变量,当你使用threadLocal.set(value)方法时,其实是以ThreadLocal作为key,你设置的值作为value放置在线程内部的ThreadLocalMap中,所以不同线程间的ThreadLocal是隔离的

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

我们再看一下ThreadLocalMap类

在这里插入图片描述

Entry类继承了WeakReference类.那么Entry为什么要继承WeakReference弱引用呢?

对于ThreadLocal tl = new ThreadLocal<>();而言,如果Entry不使用弱引用而使用强引用,那么当我把tl=null时,GC依然无法回收ThreadLocal对象,因为再ThreadLocalMap中的Entry依然存在一个引用指向了ThreadLocal,造成对象无法回收,存在内存泄漏.所以需要将Entry设置为弱引用.但是还是存在内存泄漏的问题.因为key是弱引用被回收变成了null,但是value依然存在且无法被回收,所以当threadlocal不再使用时,一定要调用threadLocal.remove()方法

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值