TransmittableThreadLocal详解,源码分析,一文带你掌握核心逻辑
这篇文章主要想向大家介绍TransmittableThreadLocal的基本原理,具体应用其实就是在使用线程池的时候支持threadLocal的子线程传递
大家可能会说Jdk自带的InheritableThreadLocal不是已经实现了ThreadLocal的传递吗?为什么还需要TransmittableThreadLocal。
如果大家有看过InheritableThreadLocal的源代码就会发现,InheritableThreadLocal的传递是发生在新建线程的时候,但是在我们项目中基本都是用线程池来使用多线程,因为线程的创建销毁都会有资源消耗,当然也有可能发生oom,具体就不多说了。
TransmittableThreadLocal就解决了线程池维度下的ThreadLocal传递,大家可以浅浅思考一下怎么改变一下,就可以实现线程复用的情况下也可以传递ThreadLocal。
其实就是把传递ThreadLocal的逻辑放在run方法的前面就解决了,思想就是这么简单,但是却很巧妙,使用装饰者模式把Runnable包了一层
源码分析
TransmittableThreadLocal
首先很重要的是TransmittableThreadLocal里面保存了一个静态变量holder,大家得先理解好holder
holder 变量是一个InheritableThreadLocal, 他是一个map但是一直都是当作Set在用,value一直是空
The value of holder is type WeakHashMap<TransmittableThreadLocal, ?>, but it is used as Set (aka. do NOT use about value, always null).
每次使用holder变量都会带着.get() ,意味着每次获取到的WeakHashMap都是线程自己的,这是我之前一直不理解的点,记住,每次使用holder都会带上.get(),而不是真正全局使用一个WeakHashMap
接下来来分析一下set()
方法
-
首先会将当前的value设置到Thread中的ThreadLocalMap
-
然后将当前的TransmittableThreadLocal放入当前线程的map中(给未来打快照使用)
public final void set(T value) {
// 首先先使用ThreadLocal的特性,将当前的value设置到Thread中的ThreadLocalMap,保证ThreadLocal的特性被保留
super.set(value);
// may set null to remove value
// 如果是value是null,就从map中删除
if (null == value) removeValue();
// 这一步本质就是将当前的TransmittableThreadLocal放入当前线程的map中,以保存父线程的使用过的TransmittableThreadLocal
else addValue();
}
private void addValue() {
if (!holder.get().containsKey(this)) {
// 将当前的TransmittableThreadLocal放入当前线程的map中
// 这里value一直是空
holder.get().put((TransmittableThreadLocal<Object>) this, null); // WeakHashMap supports null value.
}
}
get()
方法没有什么特殊的大家看看就行
public final T get() {
T value = super.get();
if (null != value) addValue();
return value;
}
TtlRunnable
重要!!!
我认为整个TransmittableThreadLocal的核心就是使用装饰模式,将整个Runnable 包装了一层,实现了当线程复用的情况也可以将父线程继承到子线程的能力
首先在使用TtlRunnable.get(runnable),会将Runnable包装一层,此时的调用方就是父线程,在方法中会调用capture(),获取当前父线程的快照
打快照
public static TtlRunnable get(@Nullable Runnable runnable, boolean releaseTtlValueReferenceAfterRun, boolean idempotent) {
if (null == runnable) return null;
if (runnable instanceof TtlEnhanced) {
// avoid redundant decoration, and ensure idempotency
if (idempotent) return (TtlRunnable) runnable;
else throw new IllegalStateException("Already TtlRunnable!");
}
return new TtlRunnable(runnable, releaseTtlValueReferenceAfterRun);
}
// 构造函数
private TtlRunnable(@NonNull Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {
// capture()此方法是核心
this.capturedRef = new AtomicReference<Object>(capture());
this</