我们使用InheritableThreadLocal可以保证在子线程中拿到父线程设置的ThreadLocal的值,它在创建子线程时通过复制父线程的ThreadLocal的值来保证ThreadLocal的值的传递。但是在线程池这种线程复用的场景下,不会每次都创建线程。这就导致了ThreadLocal的值传递不起作用。例如如下例子:
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,
3,
0,
TimeUnit.SECONDS,
new SynchronousQueue<>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) throws InterruptedException {
InheritableThreadLocal<Object> threadLocal = new InheritableThreadLocal<>();
threadLocal.set(5);
for(int i = 0; i < 3; i++){
threadPoolExecutor.submit(() ->{
log.info("threadlocal的值:{}", threadLocal.get());
});
}
threadLocal.remove();
Thread.sleep(1000);
threadLocal.set(3);
for(int i = 0; i < 3; i++){
threadPoolExecutor.submit(() ->{
log.info("threadlocal的值:{}", threadLocal.get());
});
}
threadLocal.remove();
}
这个时候可以使用阿里开发出来的TransmittableThreadLocal来让线程池提交任务时进行ThreadLocal的值传递。将代码稍加改造即可。
1.引入ttl的依赖。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.12.1</version>
</dependency>
2.稍加改造代码
static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3,
3,
0,
TimeUnit.SECONDS,
new SynchronousQueue<>(),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
public static void main(String[] args) throws InterruptedException {
ExecutorService ttlExecutorService = TtlExecutors.getTtlExecutorService(threadPoolExecutor);
InheritableThreadLocal<Object> threadLocal = new TransmittableThreadLocal<>();
threadLocal.set(5);
for(int i = 0; i < 3; i++){
ttlExecutorService.submit(() ->{
log.info("threadlocal的值:{}", threadLocal.get());
});
}
threadLocal.remove();
Thread.sleep(1000);
threadLocal.set(3);
for(int i = 0; i < 3; i++){
ttlExecutorService.submit(() ->{
log.info("threadlocal的值:{}", threadLocal.get());
});
}
threadLocal.remove();
}
这样就可以保证在线程池下也可以实现ThreadLocal的传递。