李锋镝的博客

  • 首页
  • 时间轴
  • 说说
  • 每日心情
  • Now
  • 系列文章
  • 论坛
  • 左邻右舍
    • 左邻右舍
    • 博友圈
  • 留言
    • 留言
    • 走心评论
  • 关于
    • 关于本站
    • 网站地图
    • 网站统计
    • 另一个网站
    • 我的导航站
    • 赞助
  • 🚇开往
!Destiny
惟坚韧者始能遂其志
  1. 首页
  2. 原创
  3. 技术
  4. 正文

TransmittableThreadLocal介绍与使用

2025年6月3日 约 1,391 字5 分钟 154 1 0
本文最后更新于 2025年6月3日,距今已 476 天,其中的信息可能已经发生变化,请注意甄别。

TransmittableThreadLocal(TTL)是阿里巴巴开源的一个 Java 库,用于解决 线程池环境下 ThreadLocal 上下文丢失 的问题。它是 InheritableThreadLocal 的增强版,特别适用于异步编程、分布式系统等场景。以下是详细解析:

一、核心问题:为什么需要 TransmittableThreadLocal?

1. 传统 ThreadLocal 的局限性

  • 线程隔离性:ThreadLocal 为每个线程提供独立的变量副本,子线程无法获取父线程的 ThreadLocal 值。
  • 线程池复用问题:线程池中的线程会被复用,InheritableThreadLocal 仅在创建子线程时复制一次值,后续任务无法获取最新的父线程上下文。

示例场景:

// 主线程设置 InheritableThreadLocal
InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
threadLocal.set("parent-value");

// 提交任务到线程池(线程复用导致上下文不更新)
ExecutorService executor = Executors.newFixedThreadPool(1);
for (int i = 0; i < 3; i++) {
    threadLocal.set("value-" + i);
    executor.submit(() -> {
        System.out.println(threadLocal.get()); // 输出固定值 "value-0"(线程池复用同一个线程)
    });
}

2. TTL 的解决方案

TransmittableThreadLocal 通过 捕获-传递-恢复 机制,确保:

  • 子线程执行时能获取父线程 最新 的上下文值。
  • 即使在线程池环境下,每次任务执行时上下文都能正确传递。

二、TransmittableThreadLocal 的工作原理

1. 核心机制

  • 捕获(Capture):在提交任务时,记录当前线程的 TransmittableThreadLocal 值。
  • 传递(Transmit):将捕获的值传递给执行任务的线程。
  • 恢复(Restore):任务执行前后,分别恢复和还原上下文,避免线程污染。

2. 关键类与方法

  • TransmittableThreadLocal<T>:继承自 ThreadLocal,扩展了上下文传递能力。
  • TtlRunnable/TtlCallable:包装 Runnable/Callable,自动处理上下文传递。
  • TtlExecutors:工具类,用于包装线程池(如 ExecutorService)。

三、使用示例

1. 基础用法

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.TtlRunnable;

public class TTLExample {
    // 创建 TTL 实例
    private static final TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();

    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(1);

        // 主线程设置上下文
        context.set("main-value");

        // 包装任务,自动传递上下文
        Runnable task = TtlRunnable.get(() -> {
            System.out.println("Task 1: " + context.get()); // 输出: "main-value"
        });

        executor.submit(task);

        // 更新上下文
        context.set("updated-value");

        // 提交另一个任务
        executor.submit(TtlRunnable.get(() -> {
            System.out.println("Task 2: " + context.get()); // 输出: "updated-value"(正确获取最新值)
        }));

        executor.shutdown();
    }
}

2. 包装线程池

// 包装线程池,自动处理所有提交的任务
ExecutorService executor = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(2));

// 直接提交任务,无需手动包装
executor.submit(() -> {
    System.out.println("Task in wrapped executor: " + context.get());
});

3. 与异步框架集成

// CompletableFuture 结合 TTL
CompletableFuture.runAsync(
    TtlRunnable.get(() -> { /* 任务逻辑 */ }),
    executor
);

// RxJava 结合 TTL
Observable.just("data")
    .subscribeOn(Schedulers.from(executor))
    .doOnNext(data -> {
        // 此处可获取主线程的上下文
    });

四、高级特性

1. 自定义传播规则

通过 Transmitter 接口自定义上下文的捕获、传递和恢复逻辑:

TransmittableThreadLocal<String> ttl = new TransmittableThreadLocal<String>() {
    @Override
    protected String copy(String parentValue) {
        // 自定义复制逻辑(如深拷贝)
        return parentValue != null ? new String(parentValue) : null;
    }
};

2. 上下文清除

使用 ClearTtlValueFilter 自动清除不需要传递的上下文:

// 注册过滤器,清除某些 TTL 值
public class MyClearFilter implements ClearTtlValueFilter {
    @Override
    public boolean clear(Object value) {
        return value instanceof SensitiveData; // 清除敏感数据
    }
}

// 全局注册过滤器
TtlFilters.registerClearTtlValueFilter(new MyClearFilter());

五、适用场景

场景 说明
分布式链路追踪 传递 TraceID、SpanID 等上下文,确保跨线程调用的追踪连续性。
用户会话管理 在异步任务中保持用户认证信息(如 Session、JWT)。
多租户系统 传递租户 ID,确保子线程正确访问租户数据。
事务上下文 在异步事务中传递 Transaction ID 或隔离级别。
日志 MDC(Mapped Diagnostic Context) 传递日志上下文(如请求 ID),便于日志聚合和分析。

六、与其他方案的对比

方案 优点 缺点 适用场景
ThreadLocal 简单,线程隔离 不支持跨线程传递 单线程上下文存储
InheritableThreadLocal 支持父子线程传递 线程池环境下上下文不更新 固定线程创建场景(非线程池)
手动传递上下文 完全可控,无依赖 代码侵入性强,需修改所有方法签名 小规模项目或简单场景
TransmittableThreadLocal 零代码侵入,支持线程池和异步框架 需引入依赖,有一定性能开销 复杂异步系统、分布式应用

七、注意事项

  1. 性能开销:TTL 会增加每次任务提交和执行的开销(约 10-20%),对性能敏感的系统需谨慎评估。
  2. 内存泄漏风险:若存储大对象且未及时清理,可能导致内存泄漏,建议配合 try-finally 手动清除。
  3. 兼容性:与部分框架(如 Hystrix)集成时需额外配置,可能需要自定义传播器。
  4. 版本依赖:推荐使用最新版本(如 2.14.2+),修复了多个已知问题。

八、总结

TransmittableThreadLocal 是解决 异步编程中上下文传递问题 的利器,特别适合复杂的分布式系统和线程池环境。通过简单的包装,即可实现透明的上下文传播,避免手动传递的代码冗余和错误风险。在高并发场景下,需权衡性能开销,必要时结合异步框架的原生上下文机制(如 Reactor 的 Context)使用。

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/article/tech/4439

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
分享到

TransmittableThreadLocal介绍与使用

也可使用浏览器菜单中的「分享」功能

微信扫一扫分享

标签: InheritableThreadLocal JAVA ThreadLocal TransmittableThreadLocal 多线程 线程 线程安全 线程池
最后更新:2025年6月3日

岁月同一天 9 月 22 日

回望过去的今天,你在写什么

  • 3 年前 2023年9月22日
    《人生海海》读后感

    前段时间读完了麦家的《人生海海》,起初对人生海海这个词不太理解,记得第一次听到这个词,应该是在《欢喜就好》这首歌里,里面…

  • 4 年前 2022年9月22日
    OHCache使用

    OHCache介绍 缓存框架OHC基于Java语言实现,并以类库的形式供其他Java程序调用,是一种以单机模式运行的堆外…

相关文章
  • JDK25模块级导入深度解析:Java导入机制的革命性进化2026年1月26日
  • 解决Cannot connect to core dump or remote debug server. Use jhsdb jmap instead2025年4月9日
  • Java通用枚举还能这样做?前后端终于不扯皮了!2025年10月21日
  • Java设计模式-原型模式2020年1月10日
  • 从零开始入门 K8s | Kubernetes 网络概念及策略控制2019年10月17日

李锋镝

既然选择了远方,便只顾风雨兼程。

打赏 点赞
< 上一篇
下一篇 >
1234567891112131415161718192021222324252627282930313233343536373839404142434446474849505152535455575859606162636465666769727476777879808182858687909293949596979899
取消回复
…

文章评论

还没有评论,快来抢沙发吧~

曾经沧海难为水,除却巫山不是云。

听点儿音乐吧 朋友~
文章目录
最新 热点 随机
最新 热点 随机
让WordPress静态化之Rocket‑Nginx WordPress下一代默认主题Ipsum预览 C++之父重磅发声:AI编程正在毁掉一代程序员 支撑全网40%网站的WordPress正在重新拥抱PHP生态 Kratos-plus v1.1.24版本更新说明 关于主题加载速度优化的一点儿小演进
关于主题加载速度优化的一点儿小演进给主题增加了Now、每日心情、年度回顾、岁月同一天、随机漫步等功能WordPress缓存插件WP Fastest Cache、WP Rocket 、FlyingPress对比关于使用AI的一些思考WordPress下一代默认主题Ipsum预览Kratos+ v1.1.16版本更新说明
网站升级到http/2 为什么 Apache Doris 是比 Elasticsearch 更好的实时分析替代方案? 为什么关于香菜的评价这么两极? 妹妹的画【2019.07.13】 Redis 不只是缓存:8 大实战场景 + 深度避坑指南,从入门到架构师级应用 分库分表正在被淘汰?NewSQL与分库分表的深度博弈与选型指南
最近评论
李锋镝 发布于 2 小时前(09月22日) 是的,换风格了,不过我觉得之前的年份命名挺好的,一看就知道哪一年的
obaby 发布于 5 小时前(09月22日) 我现在是个假的wp了,哈哈哈 wp终于改了主题的命名风格了
李锋镝 发布于 2 天前(09月20日) 静态博客我之前也用过,但是感觉不是很方便,后来就一直用的WordPress
Sheep5 发布于 2 天前(09月20日) 我直接用静态博客,天然有速度优势。
不凡 发布于 2 天前(09月20日) 主要是wordpress插件丰富,需要什么功能插件,插件市场应有尽有,typecho是性能更好、更轻...
标签聚合
WordPress JAVA IDEA MQ SQL 架构 ElasticSearch 分布式 AI编程 日常 MySQL K8s 多线程 SpringBoot 数据库 JVM Redis Spring Claude AI
友情链接
  • lijie blog
  • 若梦博客
  • 哥斯拉
  • 知向前端
  • Honesty
  • 蜗牛工作室
  • 懋和道人
  • 皮皮社
  • 瓦匠个人小站
  • 志文工作室
  • 彬红茶日记
  • 韩小韩博客
  • 老张博客
  • sssr7844的博客
  • 九仞之行
  • Serendipity
  • Mr.Sun的博客
  • 林羽凡
  • 搬砖日记
  • 韩情脉脉

COPYRIGHT © 2016-2026 lifengdi.com. ALL RIGHTS RESERVED.

lifengdi.com

Domain age badge for lifengdi.com

Theme Kratos-plus By Dylan Li

津ICP备2024022503号-3

京公网安备11011502039375号