1、简介

TransmittableThreadLocal 是Alibaba开源的、用于解决 “在使用线程池等会缓存线程的组件情况下传递ThreadLocal” 问题的 InheritableThreadLocal 扩展。若希望 TransmittableThreadLocal 在线程池与主线程间传递,需配合 TtlRunnableTtlCallable 使用。

2、使用场景

下面是几个典型场景例子。

  1. 分布式跟踪系统
  2. 应用容器或上层框架跨应用代码给下层SDK传递信息
  3. 日志收集记录系统上下文

3、源码分析

TransmittableThreadLocal 继承自 InheritableThreadLocal,这样可以在不破坏ThreadLocal 本身的情况下,使得当用户利用 new Thread() 创建线程时仍然可以达到传递InheritableThreadLocal 的目的。

public class TransmittableThreadLocal<T> extends InheritableThreadLocal<T> { ...... }

TransmittableThreadLocal 相比较 InheritableThreadLocal 很关键的一点改进是引入holder变量,这样就不必对外暴露Thread中的 inheritableThreadLocals(参考InheritableThreadLocal详解),保持ThreadLocal.ThreadLocalMap的封装性。

// 理解holder,需注意如下几点:
// 1、holder 是 InheritableThreadLocal 变量;
// 2、holder 是 static 变量;
// 3、value 是 WeakHashMap;
// 4、深刻理解 ThreadLocal 工作原理;
private static InheritableThreadLocal<Map<TransmittableThreadLocal<?>, ?>> holder =new InheritableThreadLocal<Map<TransmittableThreadLocal<?>, ?>>() {@Overrideprotected Map<TransmittableThreadLocal<?>, ?> initialValue() {return new WeakHashMap<>();}@Overrideprotected Map<TransmittableThreadLocal<?>, ?> childValue(Map<TransmittableThreadLocal<?>, ?> parentValue) {return new WeakHashMap<>(parentValue);}};

个人认为 holder 变量的设计,极大体现了作者的智慧,让人无数次献上膝盖。。。

// 调用 get() 方法时,同时将 this 指针放入 holder
public final T get() {T value = super.get();if (null != value) {addValue();}return value;
}
void addValue() {if (!holder.get().containsKey(this)) {holder.get().put(this, null); // WeakHashMap supports null value.}
}
// 调用 set() 方法时,同时处理 holder 中 this 指针
public final void set(T value) {super.set(value);if (null == value) { // may set null to remove valueremoveValue();} else {addValue();}
}
void removeValue() {holder.get().remove(this);
}

4、工作流程简介

自定义 TtlRunnable 实现 Runnable,TtlRunnable初始化方法中保持当前线程中已有的TransmittableThreadLocal

private TtlRunnable(Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {this.copiedRef = new AtomicReference<Map<TransmittableThreadLocal<?>, Object>>(TransmittableThreadLocal.copy());this.runnable = runnable;this.releaseTtlValueReferenceAfterRun = releaseTtlValueReferenceAfterRun;
}

线程池中线程 调用run方法,执行前先backup holder中所有的TransmittableThreadLocal, copiedRef中不存在,holder存在的,说明是后来加进去的,remove掉holder中的;将copied中的TransmittableThreadLocal set到当前线程中

public void run() {Map<TransmittableThreadLocal<?>, Object> copied = copiedRef.get();if (copied == null || releaseTtlValueReferenceAfterRun && !copiedRef.compareAndSet(copied, null)) {throw new IllegalStateException("TTL value reference is released after run!");}Map<TransmittableThreadLocal<?>, Object> backup = TransmittableThreadLocal.backupAndSetToCopied(copied);try {runnable.run();} finally {TransmittableThreadLocal.restoreBackup(backup);}
}

执行后再恢复 backup 的数据到 holder 中(backup中不存在,holder中存在的TransmittableThreadLocal,从holder中remove掉),将 backup 中的 TransmittableThreadLocal set到当前线程中

5、参考文献

  1. transmittable-thread-local

TransmittableThreadLocal相关推荐

  1. 每日一博 - ThreadLocal VS InheritableThreadLocal VS TransmittableThreadLocal

    文章目录 ThreadLocal 核心API ThreadLocal类 源码分析 set get remove 缺陷 InheritableThreadLocal 源码解析 局限性 Transmitt ...

  2. TransmittableThreadLocal 解决 线程池线程复用 无法复制 InheritableThreadLocal 的问题

    ThreadLoacl,InheritableThreadLocal,原理,以及配合线程池使用的一些坑 TransmittableThreadLocal 原理 之前为了能让InheritableThr ...

  3. TransmittableThreadLocal 解决 线程池线程复用 无法复制 InheritableThreadLocal 的问题.

    ThreadLoacl,InheritableThreadLocal,原理,以及配合线程池使用的一些坑 TransmittableThreadLocal 原理 之前为了能让InheritableThr ...

  4. TransmittableThreadLocal详解

    1.简介 TransmittableThreadLocal 是Alibaba开源的.用于解决 "在使用线程池等会缓存线程的组件情况下传递ThreadLocal" 问题的 Inher ...

  5. 何为TransmittableThreadLocal

    一.示例 线程池内的线程并没有父子关系,所以不适合InheritableThreadLocal的使用场景 public class ThreadPoolInheritableThreadLocalDe ...

  6. 通过transmittable-thread-local源码理解线程池线程本地变量传递的原理

    前提 最近一两个月花了很大的功夫做UCloud服务和中间件迁移到阿里云的工作,没什么空闲时间撸文.想起很早之前写过ThreadLocal的源码分析相关文章,里面提到了ThreadLocal存在一个不能 ...

  7. TransmittableThreadLocal的简单使用 + 手写源码

    文章目录 使用方法 原理 手写源码 之前有一篇文章谈到链路追踪场景下,需要在异步线程之间,实现跨线程的ThreadLocal传递, 简单场景可以用InheritableThreadLocal,但ITL ...

  8. ThreadLocal线程池使用和TransmittableThreadLocal值传递

    一.ThreadLocal配合线程池 注意配合remove方法,线程池是对线程进行复用的,如果没有及时的清理,那么之前对该线程的使用,就会影响到后面的线程了,造成数据不准确. package com. ...

  9. 我居然被TransmittableThreadLocal框架作者评论了

    大家好,我叫大鸡腿,大家可以关注下我,会持续更新技术文章还有人生感悟,感谢~ 前言 在掘金关注我的读者,可能不知道我之前是在csdn博客写了5年的博客专家,默默无闻的写了500多篇文章,当然有些是在前 ...

最新文章

  1. 转程序员,都去写一写前端代码吧
  2. MongoDB基础教程系列--目录结构
  3. ERROR 2059 (HY000): Authentication plugin ‘caching_sha2_password‘ cannot be loaded
  4. 贪心算法之——背包问题(nyoj106)
  5. 邮票的孔怎么做出来的_金银花茶是怎么做出来的呢
  6. 源码解析Spring Boot2默认数据库连接池HikariCP(高性能原因分析)
  7. 函数的基本知识,定义,调用,参数,返回值,说明文档,函数的嵌套及应用
  8. linux 下rpm软件的安装和卸载
  9. 一个Maven工程中,不同的模块需要不同的JDK进行编译的解决方案
  10. 【Windows】要不要升级Win11?Win11与Win10界面对比体验
  11. 西门子PLC学习记录
  12. 用 C 语言来刷 LeetCode,网友直呼:那是真的牛批...
  13. wr720n刷成网络打印_USB打印机通过路由共享wifi局域网打印,同网段
  14. Python 使用 PyOTP 实现二步验证
  15. 项目经历怎么写_工作经历、项目经验怎么写?
  16. Python爬取雪球7*24小时信息
  17. Eclipse3.5中安装maven插件出现“ the -vm option in eclipse.ini is pointing to a JDK”解决
  18. .Net6 图片转文字PictureToTxt
  19. 【数据结构】递归斐波那契数列的时间复杂度、空间复杂度
  20. vue 上传文件 和 下载文件

热门文章

  1. java中字符串的操作_java中字符串的操作
  2. python梯度下降法实现线性回归_梯度下降法的python代码实现(多元线性回归)
  3. sql的加减乘除运算_SQL简单查询语、运算符学习和练习
  4. 计算机科学入门指南游戏攻略,【基础攻略】从零开始新手入门指南
  5. STM32 ADC采样使用内部参考电压
  6. 手动修改Win7开机欢迎界面背景图片
  7. jsp页面实现打印 .
  8. mysql不存在就批量新增_mysql批量插入,存在则修改,不存在则插入
  9. ps自定义形状工具_【福利】3000款PS自定义形状免费打包下载
  10. docker pull的镜像放在哪里_Docker 安装ELK及Docker常见命令