文章目录
TransmittableThreadLocal
一、概述
1、背景
大多数系统会使用线程池技术,这已经不仅仅是InheritableThreadLocal
能够解决的了。
TransmittableThreadLocal
是Alibaba开源,用于实现 在使用线程池等 会缓存线程的组件时 传递ThreadLocal。
2、使用场景
下面是几个典型场景例子。
- 分布式跟踪系统
- 应用容器或上层框架跨应用代码给下层SDK传递信息
- 日志收集记录系统上下文
3、maven依赖
<!-- TransmittableThreadLocal -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.14.2</version>
</dependency>
4、生效前提
当我们使用线程池时,要使得线程池的变量传递起效果,需要:
-
使用
TtlRunnable.get(runnable)
对Runnable
进行包装使用
TtlCallable.get(callable)
对Callable
进行包装 -
使用
TtlExecutors.getTtlExecutor
对Executor
进行包装使用
TtlExecutors.getTtlExecutorService
对ExecutorService
进行包装使用
TtlExecutors.getTtlScheduledExecutorService
对ScheduledExecutorService
进行包装
第二种方式其实就是在 execute
和 submit
时通过 TtlRunnable
或 TtlCallable
对原任务进行包装
至于为什么要这样,可以在下面的源码分析中找到答案。
二、源码分析 - TransmittableThreadLocal
TransmittableThreadLocal
继承自 InheritableThreadLocal
public class TransmittableThreadLocal<T> extends InheritableThreadLocal<T> implements TtlCopier<T> {
}
使得当用户利用 new Thread()
创建线程时仍然可以达到传递InheritableThreadLocal
的目的。
1、构造方法
// com.alibaba.ttl.TransmittableThreadLocal
public TransmittableThreadLocal() {
this(false);
}
public TransmittableThreadLocal(boolean disableIgnoreNullValueSemantics) {
// 是否忽略null值set,默认false
this.disableIgnoreNullValueSemantics = disableIgnoreNullValueSemantics;
}
2、holder
TransmittableThreadLocal
相比较 InheritableThreadLocal
很关键的一点改进是引入了holder
变量
这样就不必对外暴露 Thread
中的 inheritableThreadLocals
,保持 ThreadLocal.ThreadLocalMap
的封装性。
// com.alibaba.ttl.TransmittableThreadLocal
// holder其实就是InheritableThreadLocal的一个匿名内部类
private static final InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal<Object>, ?>> holder =
new InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal<Object>, ?>>() {
@Override
protected WeakHashMap<TransmittableThreadLocal<Object>, ?> initialValue() {
return new WeakHashMap<>();
}
@Override
protected WeakHashMap<TransmittableThreadLocal<Object>, ?> childValue(
WeakHashMap<TransmittableThreadLocal<Object>, ?> parentValue
) {
return new WeakHashMap<>(parentValue);
}
};
holder
其实就是InheritableThreadLocal
的一个匿名内部类。holder
由final static
修饰。holder
存储的是WeakHashMap
,key 是TransmittableThreadLocal<Object>
对象,value 是对应的值WeakHashMap
的key
是WeakReference
弱引用,方便回收
3、set 方法
// com.alibaba.ttl.TransmittableThreadLocal
// 调用 set() 方法时,同时处理 holder 中 this 指针
@Override
public final void set(T value) {
if (!disableIgnoreNullValueSemantics && value == null) {
// 不忽略null写入,则移除本地线程变量
remove();
} else {
// 调用父类ThreadLocal的set方法
super.set(value);
// 添加到 holder 中
addThisToHolder();
}
}
private void addThisToHolder() {
if (!holder.get().containsKey(this)) {
// WeakHashMap supports null value.
holder.get().put((TransmittableThreadLocal<Object>) this, null);
}
}
4、remove 方法
// com.alibaba.ttl.TransmittableThreadLocal
// 调用 remove() 方法时,同时remove holder 中 this 指针
@Override
public final void remove() {
// 从 holder 中移除
removeThisFromHolder();
// 调用父类ThreadLocal的remove方法
super.remove();
}
private void removeThisFromHolder() {
holder.get().remove(this);
}
5、get 方法
// com.alibaba.ttl.TransmittableThreadLocal
// 调用 get() 方法时,同时将 this 指针放入 holder
@Override
public final T get() {
// 调用父类ThreadLocal的get方法
T value = super.get();
// 如果允许忽略null,或者value不为null,再次添加到holder
if (disableIgnoreNullValueSemantics || value != null)
addThisToHolder();
return value;
}
private void addThisToHolder() {
if (!holder.get().containsKey(this)) {
// WeakHashMap supports null value.
holder.get().put((TransmittableThreadLocal<Object>) this, null);
}
}
三、源码分析 - TtlExecutors
public final class TtlExecutors {
public static Executor