点击领取优惠~
473 字
2 分钟
ThreadLocal 怎么实现的呢?
ThreadLocal 怎么实现的呢?
我们看一下 ThreadLocal 的 set(T)方法,发现先获取到当前线程,再获取ThreadLocalMap,然后把元素存到这个 map 中。
public void set(T value) { //获取当前线程 Thread t = Thread.currentThread(); //获取ThreadLocalMap ThreadLocalMap map = getMap(t); //讲当前元素存入map if (map != null) map.set(this, value); else createMap(t, value); }ThreadLocal 实现的秘密都在这个ThreadLocalMap了,可以 Thread 类中定义了一个类型为ThreadLocal.ThreadLocalMap的成员变量threadLocals。
public class Thread implements Runnable { //ThreadLocal.ThreadLocalMap是Thread的属性 ThreadLocal.ThreadLocalMap threadLocals = null;}ThreadLocalMap 既然被称为 Map,那么毫无疑问它是<key,value>型的数据结构。我们都知道 map 的本质是一个个<key,value>形式的节点组成的数组,那 ThreadLocalMap 的节点是什么样的呢?
static class Entry extends WeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value;
//节点类 Entry(ThreadLocal<?> k, Object v) { //key赋值 super(k); //value赋值 value = v; }}这里的节点,key 可以简单低视作 ThreadLocal,value 为代码中放入的值,当然实际上 key 并不是 ThreadLocal 本身,而是它的一个弱引用,可以看到 Entry 的 key 继承了 WeakReference(弱引用),再来看一下 key 怎么赋值的:
public WeakReference(T referent) { super(referent);}key 的赋值,使用的是 WeakReference 的赋值。
ThreadLoca结构图
所以,怎么回答 ThreadLocal 原理?要答出这几个点:
- Thread 类有一个类型为 ThreadLocal.ThreadLocalMap 的实例变量 threadLocals,每个线程都有一个属于自己的 ThreadLocalMap。
- ThreadLocalMap 内部维护着 Entry 数组,每个 Entry 代表一个完整的对象,key 是 ThreadLocal 的弱引用,value 是 ThreadLocal 的泛型值。
- 每个线程在往 ThreadLocal 里设置值的时候,都是往自己的 ThreadLocalMap 里存,读也是以某个 ThreadLocal 作为引用,在自己的 map 里找对应的 key,从而实现了线程隔离。
- ThreadLocal 本身不存储值,它只是作为一个 key 来让线程往 ThreadLocalMap 里存取值。
ThreadLocal 怎么实现的呢?