CodeArena

使用Transmittable-Thread-Local作为线程上下文传递解决方案

2023-04-13
Java
最后更新:2024-05-23
4分钟
625字

使用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 方法。

1
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
2
/**
3
* 设置线程的ThreadLocalMap
4
*/
5
protected void setThreadLocalMap(ThreadLocalMap map) {
6
threadLocals = map;
7
}
8
9
/**
10
* 获取线程的ThreadLocalMap
11
*/
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
else
36
createMap(t, value);
37
return value;
38
}
39
40
/**
41
* 创建ThreadLocalMap
42
*/
43
void createMap(Thread t, T firstValue) {
44
t.threadLocals = new ThreadLocalMap(this, firstValue);
45
}
46
47
/**
48
* 获取线程的ThreadLocalMap
49
*/
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 maintained
2
* by the ThreadLocal class. */
3
ThreadLocal.ThreadLocalMap threadLocals = null;
4
5
/*
6
* InheritableThreadLocal values pertaining to this thread. This map is
7
* maintained by the InheritableThreadLocal class.
8
*/
9
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

如果是在父线程中创建的子线程,那么子线程会继承父线程的inheritableThreadLocals,如果子线程中没有设置inheritableThreadLocals,那么子线程会继承父线程的threadLocals。

但是在实际应用场景中,我们基本上都是使用线程池,线程池使用线程复用的技术,而inheritableThreadLocals是在创建子线程的时候设置的,所以在这种场景下inheritableThreadLocals就失去了意义。

本文标题:使用Transmittable-Thread-Local作为线程上下文传递解决方案
文章作者:Echoidf
发布时间:2023-04-13
感谢大佬送来的咖啡☕
alipayQRCode
wechatQRCode