java ThreadLocal 原理说明

准备工作

创建一个共享变量ThreadLocal

再创建一个向共享变量ThreadLocal 中赋值的线程

再创建一个从共享变量ThreadLocal 中取值的线程

如下图所示:tl为共享变量ThreadLocal

TestThreadForSet 为赋值线程;TestThreadForGet 为取值线程,

为保证赋值线程先于取值线程执行,中间加入了等待2秒

java ThreadLocal 原理说明_第1张图片

java ThreadLocal 原理说明_第2张图片

java ThreadLocal 原理说明_第3张图片

运行结果:

如果ThreadLocal 为普通的共享变量,那么取到的值一定为赋值线程中设置的值。

然而:实际运行结果如下:

java ThreadLocal 原理说明_第4张图片

下面来说明为什么会这样:

首先我们需要了解赋值线程赋值的时候,把值存储到哪里去了?

我们跟踪下ThreadLocal的set方法

java ThreadLocal 原理说明_第5张图片

1:首先获取当前线程,然后执行了getMap方法,参数为当前线程,我们下面看getMap方法

java ThreadLocal 原理说明_第6张图片

这里是重点,直接返回的是线程内部的实例变量threadLocals,注意这里是线程内部的实例变量,也就是说实际运行过程中每个线程都有一个threadLocals变量,这个变量的类型ThreadLocalMap。如下图

java ThreadLocal 原理说明_第7张图片

2:getMap执行完后,我们再返回到set方法中,这个时候会判断map是否为空,因为我们是第一次赋值,所以map肯定为null

,然后执行createMap方法,方法参数为当前线程对象,以及你要赋值的变量。

3:我们看到这里给线程的threadLocals变量赋值了一个新的对象,这里再次声明一下,threadLocals是当前线程的实例变量,每个线程不共享,即如果有10个线程那么就会有10个threadLocals变量,每个线程一个。下面我们看new ThreadLocalMap(this, firstValue);做了什么,这个构造方法中第一个参数为this,这个this指向的是threadLocal变量,也就是在main方法中声明的变量tl,看下图

注意跟上面的threadLocals区分开;这个构造方法中第二个参数为你赋值的内容。

java ThreadLocal 原理说明_第8张图片

4:上图中构造方法里的内容,这里总结成一句话就是 以Threadlocal(这里没有s)变量对象为key,以你赋值的内容为value放到ThreadLocalMap中。

总结一下,下图中这几条语句的主要逻辑是,首先获取当前线程中的一个实例变量map,如果获取到的map为空,那么就创建一个map,并把ThreadLocal变量作为key,自定义赋值内容为value放到map中,如果不为空,那就直接放了,相信很多同学都写过这样的逻辑。

java ThreadLocal 原理说明_第9张图片

到此为止,我们讲了set方法的逻辑。下面我们看下get方法的逻辑,get方法的逻辑其实就是到当前线程的threadLocals变量(ThreadLocalMap类型)里找this为key对应的value,this变量指的是ThreadLocal共享变量tl。注意这里又提到了当前线程。

java ThreadLocal 原理说明_第10张图片

我们用一张图总结一下上面的内容

java ThreadLocal 原理说明_第11张图片

你可能感兴趣的:(java)