ThreadLocal用法详解及源码讲解

      ThreadLocal的作用是为每一个使用该变量的线程提供单独的副本,每个线程可以单独修改属于变量副本而不影响

其他线程的变量副本,这大概也就是ThreadLocal单词中“Local”所要表达的意思,个人理解这个ThreadLocal有点和

volatile相反的意思,好了不多说了,直接上源码吧。。。。。。

先来看set方法

 java.lang.ThreadLocal类中

代码段1      

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

这一句不用多说,获取当前的运行线程

Thread  t = Thread.currentThread();

----------------------------------

下面继续看  getMap(t) 源码

代码段2

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

直接返回当前执行线程对象的 threadLocals 变量,

而这个变量在Thread类中定义为:

代码段3

ThreadLocal.ThreadLocalMap threadLocals = null;

也就是说当前执行线程第一次执行set方法时,threadLocals为null.

在看代码段1,当map为空时,会进入else分支,执行 createMap(t,value)

下面来看此方法的源码

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

看到这里,不熟悉的读者可能会有一个疑问, ThreadLocalMap是什么?

ThreadLocalMap 是ThreadLocal的静态内部类,用于保存线程中ThreadLocal的数据结构。ThreadLocal内部就是通过操作ThreadLocalMap从而实现的ThreadLocal的存储。有点类似于HashMap, 对HashMap源码不是很了解的,可能对ThreadLocalMap的源码难以理解.  而ThreadLocalMap又有一个静态内部类Entry,因此,在ThreadLocalMap中管理的也就是Entry对象。也就是说,ThreadLocalMap里面的大部分函数都是针对Entry的,ThreadLocalMap里面存储的Entry对象本质上是一个WeakReference<ThreadLocal>。也就是说,ThreadLocalMap里面存储的对象本质是一个对ThreadLocal对象的弱引用,该ThreadLocal随时可能会被回收!即导致ThreadLocalMap里面对应的ValueKeynull ,这里为什么使用弱引用不做过多解释。

此段代码以this也即当前ThreadLocal对象作为key, set(T value)方法中的value作为value,创建ThreadLocalMap对象,并赋值给当前执行线程中的threadLocals变量。至此,set(T value)方法执行完毕。

接下来看get方法,其源码为

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

getMap(t) 就是获取当前执行线程所维护的ThreadLocalMap,  如果此map不为空,且存在key为当前ThreadLocal的Entry,则直接返回其值,

如果map为空,则会调用setInitiaValue()方法进行初始化,也即会初始化一个key为当前ThreadLocal,value为null的ThreadLocalMap,并返回null.

remove()方法就不在讲了,如果set get方法都弄清楚了,remove方法不用自己看也就懂了。

至此,ThreadLocal是如何为每一个线程提供独立变量副本的就讲解完毕,不是太难。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值