当我们用springboot使用ThreadPoolTaskExecutor时,会发现TransmittableThreadLocal跨线程共享数据不生效了,为什么?原因是没有使用threadPoolTaskExecutor.setTaskDecorator(TtlRunnable::get),今天就来仔细研究一下。
网上有很多帖子都讲了TransmittableThreadLocal工作原理,总的说来依靠TtlRunnable分成capture、replay、restore三阶段,即:
- 初始化时程序还在父线程里,此时获取到父线程的一个快照
- run的时候先对父线程快照进行重放,同时拿到当前线程的一个备份,再真正去执行我们的异步逻辑
- run结束后,再对刚刚拿到的备份做恢复
这里不做过多说明,参考下面源码。
当我们用springboot使用ThreadPoolTaskExecutor时,会发现这不逻辑不生效了,为什么?原因就是这个逻辑是TtlRunnable的,只有使用TtlRunnable对线程进行包装才能生效。怎么做呢?我们分析一下ThreadPoolTaskExecutor,发现在initializeExecutor的时候有这样一个判断
当taskDecorator存在时,将使用taskDecorator.decorate(command)来包装真正的执行逻辑。所以我们只需要使用threadPoolTaskExecutor.setTaskDecorator(TtlRunnable::get),这样就可以ThreadPoolExecutor在执行时就会产生TtlRunnable,从而执行capture、replay、restore三阶段,最终实现ThreadLocal在线程间传递。