作者:微信小助手
发布时间:2022-06-02T09:41:38
前面在介绍分布式链路追踪时讲过异步调用会丢失链路信息,最终的解决方案是使用对应的包装类重新包装一下,如下: 还有openFeign异步请求丢失上文的问题,这些问题追根究底都是ThreadLocal惹得祸。 由于ThreadLocal只能保存当前线程的信息,不能实现父子线程的继承。 说到这,很多人想到了InheritableThreadLocal,确实InheritableThreadLocal能够实现父子线程间传递本地变量,但是..... 但是你的程序如果采用线程池,则存在着线程复用的情况,这时就不一定能够实现父子线程间传递了,因为在线程在线程池中的存在不是每次使用都会进行创建, 所以若本次使用的子线程是已经被池化的线程,从线程池中取出线下进行使用,是没有经过初始化的过程,也就不会进行父子线程的本地变量拷贝。 由于在日常应用场景中,绝大多数都是会采用线程池的方式进行资源的有效管理。 今天就来聊一聊阿里的ThansmittableThreadLocal是如何解决线程池中父子线程本地变量传递。 B站链接:https://b23.tv/RI06iZl 下方是本篇文章视频教程,讲解更加详细! 帅气的人都点赞了~ 在介绍 上述代码中创建了一个单一线程池,循环异步调用,打印一下username,由于核心线程数是1,势必存在线程的复用。 打印信息如下: 看到了吗?这里并没有实现父子线程间的变量传递,这也就是InheritableThreadLocal 的局限性。 整个 需求场景: 官网地址:https://github.com/alibaba/transmittable-thread-local 下面就以上面的例子改造成TransmittableThreadLocal试一下效果。 首选需要引入对应的依赖,如下:
InheritableThreadlocal
是在线程初始化时intertableThreadLocals=true
才会进行拷贝传递。
“
InheritableThreadLocal 的问题
ThansmittableThreadLocal
之前先来看一下InheritableThreadLocal
在线程池中的问题,如下代码:@Test
public void test() throws Exception {
//单一线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
//InheritableThreadLocal存储
InheritableThreadLocal<String> username = new InheritableThreadLocal<>();
for (int i = 0; i < 10; i++) {
username.set("公众号:码猿技术专栏—"+i);
Thread.sleep(3000);
CompletableFuture.runAsync(()-> System.out.println(username.get()),executorService);
}
}公众号:码猿技术专栏—0
公众号:码猿技术专栏—0
公众号:码猿技术专栏—0
公众号:码猿技术专栏—0
公众号:码猿技术专栏—0
公众号:码猿技术专栏—0
公众号:码猿技术专栏—0
公众号:码猿技术专栏—0
公众号:码猿技术专栏—0
公众号:码猿技术专栏—0TransmittableThreadLocal 使用
TransmittableThreadLocal
(TTL
):在使用线程池等会池化复用线程的执行组件情况下,提供ThreadLocal
值的传递功能,解决异步执行时上下文传递的问题。TransmittableThreadLocal
库的核心功能(用户API
与框架/中间件的集成API
、线程池ExecutorService
/ForkJoinPool
/TimerTask
及其线程工厂的Wrapper
)。
“
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency