⛄TransmittableThreadLocal(ttl)
TransmittableThreadLocal
GitHub地址:https://github.com/alibaba/transmittable-thread-local
pom:
1 2 3 4 5 | <dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-thread-local</artifactId> <version>2.14.2</version> </dependency> |
概要:
1、ThreadLocal 线程隔绝,不能父子线程间传递变量。
2、InheritableThreadLocal,父子线程能传递,但是只在子线程产生时传递(仅一次)。
3、TransmittableTreadLocal,需要规范的使用对应的执行器,才能父子共享同一变量。TtlExecutors.getTtlExecutorService()。
使用场景:
TransmittableThreadLocal是由阿里开发的一个线程变量传递工具包,解决了InheritableThreadLocal只能再new Thread的时候传递本地变量,无法应用到线程池的问题。可以应用来作链路追踪,传递变量等用途;
在此之前我们可以先了解下JDK中的:ThreadLocal和InheritableThreadLocal ,
InheritableThreadLocal 是 Java 中的一个类,它继承自 ThreadLocal 类。ThreadLocal 类是一个用于在多线程环境下管理线程局部变量的工具类,它可以确保在不同线程之间不会共享同一个变量。
而 InheritableThreadLocal 类则提供了额外的特性,它可以将父线程的局部变量自动传递给子线程。
InheritableThreadLocal 类的主要目的是为了解决在多线程环境下,当一个线程创建了一个 ThreadLocal 变量,而它的子线程需要使用这个变量时,子线程无法获取到父线程的变量值的问题。
为了解决这个问题,InheritableThreadLocal 类提供了一个 getInheritable 方法,它可以将父线程的变量值自动传递给子线程。
简单来说,InheritableThreadLocal 可以实现父子线程之间实现数据传递的功能。
如何使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | @SpringBootTest class SpringbootDemoApplicationTests { /** * tl */ private static final ThreadLocal<Integer> oldThreadLocal = new ThreadLocal<>(); /** * itl */ private static final InheritableThreadLocal<Integer> itlThreadLocal = new InheritableThreadLocal<>(); /** * ttl */ private static final TransmittableThreadLocal<Integer> ttlThreadLocal = new TransmittableThreadLocal<>(); @Test void itlThread() throws InterruptedException { ExecutorService tlExecutorService = Executors.newFixedThreadPool(1); oldThreadLocal. set (1); System. out .println( "oldThreadLocal main线程:" + oldThreadLocal. get ()); // 1 tlExecutorService.execute(() -> System. out .println( "oldThreadLocal 子线程:" + oldThreadLocal. get ())); // null Thread.sleep(100); System. out .println( "=================itl可以在父子线程中传递值===========================" ); ExecutorService itlExecutorService = Executors.newFixedThreadPool(1); itlThreadLocal. set (2); System. out .println( "itlThreadLocal main线程:" + itlThreadLocal. get ()); // 2 itlExecutorService.execute(() -> System. out .println( "itlThreadLocal 子线程:" + itlThreadLocal. get ())); // 2 itlThreadLocal. set (3); System. out .println( "itlThreadLocal main线程:" + itlThreadLocal. get ()); // 3 // 此处使用jdk的线程池,会导致线程复用导致数据串的问题,所以此处获取到的值还是2 itlExecutorService.execute(() -> System. out .println( "itlThreadLocal 子线程:" + itlThreadLocal. get ())); // 2 } /** * 使用ttl执行器,即使线程复用,也不会导致数据串的问题 * <p> * 为什么使用了ttl,还是会导致数据串的问题? * </p> */ @Test public void ttlThread() { ExecutorService ttlExecutorService = Executors.newFixedThreadPool(1); ttlThreadLocal. set (1); System. out .println( "ttlThreadLocal main线程:" + ttlThreadLocal. get ()); // 1 ttlExecutorService.execute(() -> System. out .println( "ttlThreadLocal 子线程:" + ttlThreadLocal. get ())); // 1 ttlThreadLocal. set (2); System. out .println( "ttlThreadLocal main线程:" + ttlThreadLocal. get ()); // 2 ttlExecutorService.execute(() -> System. out .println( "ttlThreadLocal 子线程:" + ttlThreadLocal. get ())); // 1 ttlThreadLocal. set (3); System. out .println( "ttlThreadLocal main线程:" + ttlThreadLocal. get ()); // 3 ttlExecutorService.execute(() -> System. out .println( "ttlThreadLocal 子线程:" + ttlThreadLocal. get ())); // 1 } /** * 使用ttl执行器,即使线程复用,也不会导致数据串的问题 * <p> * ttl的使用要搭配ttl线程池来使用,才不会导致数据串的问题 * </p> */ @Test public void ttlThreadFix() { ExecutorService ttlExecutorService = Executors.newFixedThreadPool(1); // 此处使用了Ttl执行器将线程池包装了一层 ttlExecutorService = TtlExecutors.getTtlExecutorService(ttlExecutorService); ttlThreadLocal. set (1); System. out .println( "ttlThreadLocal main线程:" + ttlThreadLocal. get ()); // 1 ttlExecutorService.execute(() -> System. out .println( "ttlThreadLocal 子线程:" + ttlThreadLocal. get ())); // 1 ttlThreadLocal. set (2); System. out .println( "ttlThreadLocal main线程:" + ttlThreadLocal. get ()); // 2 ttlExecutorService.execute(() -> System. out .println( "ttlThreadLocal 子线程:" + ttlThreadLocal. get ())); // 2 ttlThreadLocal. set (3); System. out .println( "ttlThreadLocal main线程:" + ttlThreadLocal. get ()); // 3 ttlExecutorService.execute(() -> System. out .println( "ttlThreadLocal 子线程:" + ttlThreadLocal. get ())); // 3 } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话