TransmittableThreadLocal解决线程池变量传递以及原理解析
TransmittableThreadLocal解决线程池变量传递以及原理解析
介绍
TransmittableThreadLocal是alibaba提供的一个工具包中的类,主要作用就是解决线程池场景下的变量传递问题。继承自InheritableThreadLocal,我们知道
InheritableThreadLocal解决了主线程与子线程之间的变量传递问题,但是在遇到线程池以及线程复用的情况下,就无能为力了,TransmittableThreadLocal通过对InheritableThreadLocal以及线程池的增强,解决了这个问题。
主要用途:
- 就是应用中对于连接池中的全局链路追踪。
- 解决例如Hystrix中出现的ThreadLocal无法传递的问题。
使用
依赖
示例代码
执行结果:
原理
TransmittableThreadLocal执行的关键原理在于以下几个类做了几件事:
TransmittableThreadLocal
TransmittableThreadLocal本身增加一个静态的holderMap,里面保存了所有使用过的TransmittableThreadLocal作为key的引用,这样在复制TransmittableThreadLocal的值到线程本身的ThreadLocal时,就可以通过该holder遍历到所有的TransmittableThreadLocal。
Transmitter和Snapshot
这两个都是TransmittableThreadLocal的内部类,前者主要是一些工具方法,后者包含了2个map,ttl2Value和threadLocal2Value,分别存储ttl设置的ThreadLocal值和父线程中其他的ThreadLocal值。其中Snapshot是一个快照,用作备份还原现场使用。
TtlRunnable
这个类就是前面使用TTL封装线程池的意义,TTL封装线程池,重写了其中的sumbit和execute等方法,使得提交到线程池中的实际Runable是封装过后的TtlRunnable,并且该类完成了复制ThreadLocal值和还原现场等操作。
用两张图可以更加详细的说明执行的过程。我们给前面的两个线程池中的线程分别命个名,然后debug代码。
我们debug到TtlRunnable初始化,可以看到此时初始化的线程是loopExecutor,也就是调用线程,理所当然此时可以制作一个调用线程的ThreadLocal快照。
然后我们debug到runnable执行时走到的replay方法,此时执行的线程就是TTL线程,也就是线程池中的线程了,此时我们当然也可以将之前保存的快照,来赋值到线程池中该线程了,此后的还原也是同理。
总结
该工具类解决了特定场景下的需求,实现方式核心就是封装+快照。非常值得学习。不过在实际中也不建议在ThreadLocal值过多或者较大时频繁使用,因为会产生过多的SnapShot临时对象增加gc负担,并且每次线程执行都会带来更多的copy和还原负担。
__EOF__

本文链接:https://www.cnblogs.com/intotw/p/14740215.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~