使用Transmittable-Thread-Local作为线程上下文传递解决方案
TransmittableThreadLocal 是阿里开源的线程上下文传递解决方案,提供了一种增强的 InheritableThreadLocal,使得线程池等组件可以正确处理线程内数据,避免并发问题。
TransmittableThreadLocal (TTL), the missing Java™ std lib(simple & 0-dependency) for framework/middleware, provide an enhanced InheritableThreadLocal that transmits values between threads even using thread pooling components.
前置知识
ThreadLocal
ThreadLocal 是一个线程内部存储类,通过它可以在指定的线程中存储数据,对不同的线程的数据进行隔离,让每个线程可以访问自己内部的 ThreadLocal 存储的数据。
每个Thread对象拥有一个ThreadLocalMap对象,这个ThreadLocalMap对象是ThreadLocal的内部类,它实现了Map接口,主要作用是存储K-V键值对,key就是ThreadLocal对象,value就是我们通过set方法存储的对象。
在线程中如果我们尝试获取其他线程的ThreadLocal对象,这个get方法会根据Thread.currentThread()获取当前线程,然后通过当前线程的ThreadLocalMap对象获取ThreadLocal对象,最后返回ThreadLocal对象对应的value。所以是无法获取其他线程的ThreadLocal对象的。
InheritableThreadLocal
InheritableThreadLocal 继承 ThreadLocal,并重写了 set、get、initialValue 方法。
1public class InheritableThreadLocal<T> extends ThreadLocal<T> {2 /**3 * 设置线程的ThreadLocalMap4 */5 protected void setThreadLocalMap(ThreadLocalMap map) {6 threadLocals = map;7 }8
9 /**10 * 获取线程的ThreadLocalMap11 */12 public T get() {13 Thread t = Thread.currentThread();14 ThreadLocalMap map = getMap(t);15 if (map != null) {38 collapsed lines
16 ThreadLocalMap.Entry e = map.getEntry(this);17 if (e != null) {18 @SuppressWarnings("unchecked")19 T result = (T)e.value;20 return result;21 }22 }23 return setInitialValue();24 }25
26 /**27 * 设置初始值28 */29 private T setInitialValue() {30 T value = initialValue();31 Thread t = Thread.currentThread();32 ThreadLocalMap map = getMap(t);33 if (map != null)34 map.set(this, value);35 else36 createMap(t, value);37 return value;38 }39
40 /**41 * 创建ThreadLocalMap42 */43 void createMap(Thread t, T firstValue) {44 t.threadLocals = new ThreadLocalMap(this, firstValue);45 }46
47 /**48 * 获取线程的ThreadLocalMap49 */50 ThreadLocalMap getMap(Thread t) {51 return t.threadLocals;52 }53}
Thread类中有两个ThreadLocalMap类型的成员变量threadLocals和inheritableThreadLocals
1 /* ThreadLocal values pertaining to this thread. This map is maintained2 * by the ThreadLocal class. */3 ThreadLocal.ThreadLocalMap threadLocals = null;4
5 /*6 * InheritableThreadLocal values pertaining to this thread. This map is7 * maintained by the InheritableThreadLocal class.8 */9 ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
如果是在父线程中创建的子线程,那么子线程会继承父线程的inheritableThreadLocals,如果子线程中没有设置inheritableThreadLocals,那么子线程会继承父线程的threadLocals。
但是在实际应用场景中,我们基本上都是使用线程池,线程池使用线程复用的技术,而inheritableThreadLocals是在创建子线程的时候设置的,所以在这种场景下inheritableThreadLocals就失去了意义。