theadlocal在全链路中的作用

125 阅读2分钟

ThreadLocal 详解

ThreadLocal对外提供;的API如下:

  •  public T get()
    从线程上下文环境中获取设置的值。
  • public void set(T value)
    将值存储到线程上下文环境中,供后续使用。
  • public void remove()
    清除线程本地上下文环境。

上述API使用简单,关键是要理解 ThreadLocal 的内部存储结果。

ThreadLocal存储结构

image.png 上图的几个关键点如下:

  •  数据存储位置
    当线程调用 threadLocal 对象的 set(Object value) 方法时,数据并不是存储在 ThreadLocal 对象中,而是存储在 Thread 对象中,这也是 ThreadLocal 的由来,具体存储在线程对象的threadLocals 属性中,其类型为 ThreadLocal.ThreadLocalMap。
  •  ThreadLocal.ThreadLocalMap
    Map 结构,即键值对,键为 threadLocal 对象,值为需要存储到线程上下文的值(threadLocal#set)方法的参数。

源码分析 ThreadLocal get方法

image.png 代码@1:获取当前线程。

代码@2:获取线程的 threadLocals 属性,在上图中已展示其存储结构。

代码@3:如果线程对象的 threadLocals 属性不为空,则从该 Map 结构中,用 threadLocal 对象为键去查找值,如果能找到,则返回其 value 值,否则执行代码@4。

代码@4:如果线程对象的 threadLocals 属性为空,或未从 threadLocals 中找到对应的键值对,则调用该方法执行初始化

image.png 代码@1:调用 initialValue() 获取默认初始化值,该方法默认返回 null,子类可以重写,实现线程本地变量的初始化。

代码@2:获取当前线程。

代码@3:获取该线程对象的 threadLocals 属性。

代码@4:如果不为空,则将 threadLocal:value 存入线程对象的 threadLocals 属性中。

代码@5:否则初始化线程对象的 threadLocals,然后将 threadLocal:value 键值对存入线程对象的threadLocals 属性中。

源码分析 ThreadLocal set方法

image.png 在掌握了 get 方法实现细节,set 方法、remove 其实现的逻辑基本一样,就是对线程对象的threadLocals 属性进行操作( Map结构)。

ThreadLocal局限性

image.png 运行结果如下:

image.png 从结果上来看,在子线程中无法访问在父线程中设置的本地线程变量,那我们该如何来解决该问题呢?

为了解决该问题,JDK引入了另外一个线程本地变量实现类 InheritableThreadLocal,接下来将重点介绍 InheritableThreadLocal 的实现原理。