transmittable-thread-local解析

12 篇文章 0 订阅

这玩意我第一次用到是在用springcloud时候,有组员跟我说希望可以用线程池异步执行。本来没啥问题,但是我们希望模块之间传递traceId(方便日志查询),我们做法是把traceid放在threadlocal里,然后feign请求时候再取出来带到下一个模块去,然后就出现问题了,最后用transmittable-thread-local解决了。

一、源码解析

点开TransmittableThreadLocal类,查看它的set、get方法

第一步都是调用threadlocal的set、get方法,不同的是多了removeValue和addValue方法。点开看看。

代码也很少,大致可以猜到有个仓库叫holder来存储或者删除当前TransmittableThreadLocal,好了让我们看看holder实现了哪些玩意。

这个类首先是静态的,也就是说多个TransmittableThreadLocal共享。其次用了InheritableThreadlocal,因为主线程写了数据到holder,线程池子线程需要拿到所以用这个。然后InheritableThreadlocal里头是一个map,结构类似threadlocalmap,包括weakhashmap也是实现entry类似的功能。(这一块都是我个人猜测作者的意思,并不是很确定)

====== 到此存储部分介绍完了,接下里是介绍子线程里如何拿出来 =====

看TtlRunnable类,我们执行runnable都会用这个类包一层,看看它的get方法

这里我想说一下我看源码的习惯,我喜欢由大到小这样来看,意思是比如上图的if块,说实话我到现在都没去看它是啥玩意,但是我知道这个不是主要流程,所以我们直接看TtlRunnable的构造方法。

其他都没啥就是一个capture()方法,这个方法是在TransmittableThreadLocal类下的一个静态内部类里,由于import static所以不用写类名(虽然优雅,但是做为源码我觉得还是类名+方法名才更清晰)。这个方法就是返回父类的holder值。初始化完了就开始调用run方法了,看看他对run方法做了什么操作。

这里也是最核心的部分,再坚持一下,这部分讲完这篇废话博客就结束了!

首先是先get获取我们上面构造方法里赋值的父类holder,然后一系列校验(不是主线,跳!),然后有3个方法,replay、run、restore。我们先看run,run就是运行我们传入的run方法。那么我们可以推理出从holder里拿出来并且赋值到子线程的过程就在replay里!看看!

重点2块:

1、for里头的,对当前holder进行备份并且删除run方法开始后又插入的ttl

2、setTtlValuesTo,这个方法把值插入到子线程里

然后我们再看看restore方法

跟上面的方法差不多,也不多做解释。唯一解释一下的就是这两个方法的for循环里功能其实就为了一个目的,就是子线程执行过程中如果又新的ttl插入,那么删除,保证开始和结束时候状态一致。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值