01-InheritableThreadLocal和TransmittableThreadLocal
1.ThreadLocal存在的问题
public class TheadTest {
private static final ThreadLocal<String> THREAD_LOCAL = new ThreadLocal<>();
/**
* 当通过父线程创建子线程时,父线程ThreadLocal中的数据不会传递到子线程。
*/
public static void test01() {
THREAD_LOCAL.set("123");
new Thread(() -> {
System.out.println("==" + THREAD_LOCAL.get()); // ==null
}).start();
System.out.println(THREAD_LOCAL.get());
}
}
2.InheritableThreadLocal
- InheritableThreadLocal解决ThreadLocal的问题。
public class TheadTest {
private static final InheritableThreadLocal<String> INHERITABLE_THREAD_LOCAL = new InheritableThreadLocal<>();
/**
* InheritableThreadLocal可以在父线程创建子线程时,将父线程ThreadLocal中的数据拷贝到子线程。
* 当new Thread()时,InheritableThreadLocal会拷贝线程上下文的数据。
*/
public static void test02() {
INHERITABLE_THREAD_LOCAL.set("123");
new Thread(() -> {
System.out.println("==" + INHERITABLE_THREAD_LOCAL.get()); // ==123
}).start();
System.out.println(INHERITABLE_THREAD_LOCAL.get());
}
}
-
InheritableThreadLocal解决ThreadLocal的问题源码分析。
- Thread类中有两个ThreadLocal.ThreadLocalMap属性。
ThreadLocal.ThreadLocalMap threadLocals = null; ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
- 线程本地变量的复制在new Thread()中。
public Thread(Runnable target) { this(null, target, "Thread-" + nextThreadNum(), 0); } public Thread(ThreadGroup group, Runnable target, String name, long stackSize) { this(group, target, name, stackSize, null, true); } private Thread(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { // 之前代码省略 // inheritThreadLocals是参数传入的值为true。 // parent.inheritableThreadLocals,在INHERITABLE_THREAD_LOCAL.set("123");时 // 进行了初始化,所以parent.inheritableThreadLocals != null为true, // 程序会进入到if中,将父线程本地变量表的数据拷贝的子线程中。 if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); // 之后代码省略 }
- parent.inheritableThreadLocals初始化部分代码。
// 执行set()方法时初始化。 INHERITABLE_THREAD_LOCAL.set("123"); public void set(T value) { Thread t = Thread.currentThread(); // getMap(t)是核心的一段代码。 ThreadLocalMap map = getMap(t); if (map != null) { map.set(this, value); } else { createMap(t, value); } } // InheritableThreadLocal重写了父类ThreadLocal的getMap()方法,所有返回的是 // Thread类中inheritableThreadLocals。 ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; }
3.InheritableThreadLocal存在的问题
public class TheadTest {
private static final InheritableThreadLocal<String> INHERITABLE_THREAD_LOCAL = new InheritableThreadLocal<>();
/**
* 打印输出:
* 456
* 子线程第一次执行 123
* 子线程第二次执行 123
*
* InheritableThreadLocal在线程池的环境中,当父线程的本地变量表修改之后,
* 由父线程创建的子线程的本地变量表不会被修改。
*/
public static void test03() throws ExecutionException, InterruptedException {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1));
INHERITABLE_THREAD_LOCAL.set("123");
threadPoolExecutor.execute(() -> {
System.out.println("子线程第一次执行 " + INHERITABLE_THREAD_LOCAL.get());
});
INHERITABLE_THREAD_LOCAL.set("456");
threadPoolExecutor.execute(() -> {
System.out.println("子线程第二次执行 " + INHERITABLE_THREAD_LOCAL.get());
});
System.out.println(INHERITABLE_THREAD_LOCAL.get());
}
}
4.TransmittableThreadLocal
- 引入依赖。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.13.2</version>
</dependency>
- TransmittableThreadLocal代码事件。
public class TheadTest {
private static final TransmittableThreadLocal<String> TRANSMITTABLE_THREAD_LOCAL = new TransmittableThreadLocal<>();
/**
* 打印输出:
* 456
* pool-1-thread-1 -> 123
* pool-1-thread-1 -> 456
*
* TransmittableThreadLocal可以解决InheritableThreadLocal在线程池中子线程本地变量表不更新的问题。
*/
public static void test04() {
TRANSMITTABLE_THREAD_LOCAL.set("123");
ExecutorService executorService = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(1));
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + " -> " + TRANSMITTABLE_THREAD_LOCAL.get());
});
TRANSMITTABLE_THREAD_LOCAL.set("456");
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + " -> " + TRANSMITTABLE_THREAD_LOCAL.get());
});
System.out.println(TRANSMITTABLE_THREAD_LOCAL.get());
}
}
标签:01,Thread,THREAD,线程,TransmittableThreadLocal,INHERITABLE,InheritableThreadLocal,
From: https://www.cnblogs.com/godistance/p/16929093.html