背景
在项目中出现线程池创建的线程无法获取到创建线程的父线程main线程的信息,采用阿里开源的TtlExcutors线程池解决父子线程上下文传递问题。
简介
官方文档
TTL(transmittable-thread-local)是一个线程间传递ThreadLocal,异步执行时上下文传递的解决方案。 整个库的核心是构建在TransmittableThreadLocal类(继承并加强InheritableThreadLocal类)之上,同时包含线程池修饰(ExecutorService/ForkJoinPool/TimerTask)以及Java Agent支持,代码小于1k行,短小精悍。
Demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| static ThreadPoolExecutor executorService = (ThreadPoolExecutor)Executors.newFixedThreadPool(5); static { executorService.prestartAllCoreThreads(); } public static void main(String[] args) throws InterruptedException { TransmittableThreadLocal<String> itl = new TransmittableThreadLocal<>(); itl.set("msg"); executorService.execute(Objects.requireNonNull(TtlRunnable.get(() -> { System.out.println("InheritableThreadLocal ThreadPoolExecutor by TtlRunnable:" + itl.get()); }))); Executor ttlExecutor = TtlExecutors.getTtlExecutor(executorService); ttlExecutor.execute(() -> { System.out.println("InheritableThreadLocal ThreadPoolExecutor by TtlExecutors:" + itl.get()); }); Thread.sleep(10000); }
|
1 2
| InheritableThreadLocal ThreadPoolExecutor by TtlRunnable:msg InheritableThreadLocal ThreadPoolExecutor by TtlExecutors:msg
|
实战使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
@Configuration public class ttlThreadPoolConfig {
private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger(1);
private static final int CORE_POOL_SIZE = 4;
private static final int PLZDLX_CORE_POOL_SIZE = 2;
private static final int MAXIMUM_POOL_SIZE = 4;
private static final int KEEP_ALIVE_TIME = 60;
private static final int CAPACITY = 1000;
@Bean("ttlExecutorService") public ExecutorService executorService() { return TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor( Runtime.getRuntime().availableProcessors() * CORE_POOL_SIZE, Runtime.getRuntime().availableProcessors() * MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<>(CAPACITY), r -> new Thread(r, "Thread-ttl" + ATOMIC_INTEGER.getAndIncrement()), new MainRejectedExecutionHandler())); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
@Slf4j public final class AuthContextHolder {
private static final ThreadLocal<AuthInfo> AUTHINFO_HOLDER = new TransmittableThreadLocal<>();
private AuthContextHolder() {}
public static void clearContext() { log.debug("从线程id:{}中清除信息", Thread.currentThread().getId()); AUTHINFO_HOLDER.remove(); }
public static AuthInfo getContext() { log.debug("从线程id:{}中获取信息", Thread.currentThread().getId()); return Optional.ofNullable(AUTHINFO_HOLDER.get()).orElse(new AuthInfo()); }
public static void setContext(AuthInfo user) { log.debug("从线程id:{}中获取信息", Thread.currentThread().getId()); AUTHINFO_HOLDER.set(user); } }
|
使用:
方式一:Spring注入
1 2 3 4 5 6 7 8 9 10 11
| @Resource(name = "ttlExecutorService") private ExecutorService ttlExecutorService;
@Transactional(rollbackFor = Exception.class) public void asyncDoThings(){ ttlExecutorService.execute(() -> { AuthInfo authInfo = AuthContextHolder.getContext(); doSomeThing(); }); }
|
方式二:@Async注解
1 2 3 4 5
| @Async("ttlExecutorService") public void asyncDoThings() { AuthInfo authInfo = AuthContextHolder.getContext(); doSomeThing(); }
|
This is copyright.