《Java源码分析》:ThreadLocal /ThreadLocalMap

《Java源码分析》:ThreadLocal /ThreadLocalMap

首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set(Object obj) 到线程中的对象obj是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。

线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。

另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。

ThreadLocal适用于资源共享但不需要维护状态的情况,也就是一个线程对资源的修改,不影响另一个线程的运行;这种设计是‘空间换时间’,synchronized顺序执行是‘时间换取空间’。

在分析源码之前,先来介绍下它的内部工作原理。

假设我们在某个类中定义了一个ThreaLocal对象threadLocal。如下:

private static  ThreadLocal<String> threadLocal = new ThreadLocal<String>();

上面我们总说每个线程有一个ThreadLocal的拷贝。具体到底是怎么样的呢??

是这样的:

1、首先每个线程都有一个私有的ThreadLocalMap的引用map

2、当我们第一次调用threadLocal.set()/threadLocal.get()方法的时候会对这个map进行初始化。

3、这个ThreadLocalMap就是用来保存(threadLocal,value)这样的键值对的,即每个使用threadLocal的线程都是将其作为键而指定的值作为value保存在这个map中,而map是每个线程私有的,因此是独立的,可以随意操作。

当我们调用threadLocal.get()方法时,他首先会拿到当前线程的ThreadLocalMap对象map,由于这个ThreadLocalMap对象map中保存了(threadLocal,value)的键值对,因此根据map.get(threadLocal)来拿到相应的value值,这样我们就可以随意来操作这个value,不会影响其他线程中的value。

不知道这样说清晰了没有,如果没有,那我们就来看下ThreadLocal源码的实现。

下面我们从源码的角度来看下ThreadLocal是如何来工作的。

1、ThreadLocal的构造方法

    public ThreadLocal() {
    }

ThreadLocal只有这样一个构造方法。

2、ThreadLocal的get方法介绍

源码如下:

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t); //得到当前线程的ThreadLocalMap对象
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);  //根据ThreadLocal得到键值对对象Entry。
            //检查是否为空,如果不为空,则取出value即可,如果为空,则说明此ThreadLocal随关联的键值对被垃圾回收了,这里就再一次的调用了setInitialValue()方法进行初始化
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();//利用默认值来为当前线程创建一个ThreadLocalMap对象,如果没有重写inititalValue(),则默认值为null.
    }

get()方法的功能:返回当前线程的ThreadLocal副本中的值value,如果当前线程的这个变量没有值,则首先调用inititalValue这个方法来初始化value。

下面我们就来详细的分析下这个get方法中的代码:

1、Thread t = Thread.currentThread();

这行代码就是获取当前工作线程。即正在调用threadLocal.get()方法的线程。

2、 ThreadLocalMap map = getMap(t);

这行代码就是得到当前线程的ThreadLocalMap对象。每个线程都有一个ThreadLocalMap对象。

下面我们就先来看下这个getMap(t)方法

    //返回与ThreadLocal关联的ThreadLocalMap,每个线程对应一个ThreadLocalMap对象。
    ThreadLocalMap getMap(Thread t) {
        return t.t
  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值