ThreadLocal垮线程池传递数据解决方案:TransmittableThreadLocal【享学Java】(下)

简介: ThreadLocal垮线程池传递数据解决方案:TransmittableThreadLocal【享学Java】(下)

TransmittableThreadLocal

TTL是阿里巴巴开源的专门解决InheritableThreadLocal的局限性,实现线程本地变量在线程池的执行过程中,能正常的访问父线程设置的线程变量。


TransmittableThreadLocal简称TTL,InheritableThreadLocal简称ITL


它的官网是:https://github.com/alibaba/transmittable-thread-local

功能介绍我已截图至此:


image.png


GAV:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.11.4</version>
</dependency>


那么使用它就能解决如上示例的问题吗?正所谓试验是检验真理的唯一标准,来一把:


针对示例1,仅仅做出如下改动(其它均不变):



// 实现类使用TTL的实现
private static final ThreadLocal<Person> THREAD_LOCAL = new TransmittableThreadLocal<>();
// 线程池使用TTL包装一把
private static final ExecutorService THREAD_POOL = TtlExecutors.getTtlExecutorService

再次运行程序,控制台打印:

get数据,线程名:pool-1-thread-1,数据为:TestThreadLocal.Person(age=18)
get数据,线程名:pool-1-thread-1,数据为:TestThreadLocal.Person(age=100)



bingo!看线程名仍旧还是同一个线程(因为线程池大小为1嘛),但是结果已经是最新的了,这才是合理的嘛,不禁想感叹一句:太它xxxxx了!


说明:这里线程池必须使用TtlExecutors处理一下,而且得使用TransmittableThreadLocal作为数据传递的实现,缺一不可哦~


如何实现?


TransmittableThreadLocal继承于InheritableThreadLocal,并拥有了 InheritableThreadLocal对子线程传递上下文的特性,只需解决线程池上下文传递问题。它使用TtlRunnable包装了任务的运行,被包装的run方法执行异步任务之前,会使用replay进行设置父线程里的本地变量给当前子线程,任务执行完毕,会调用restore恢复该子线程原生的本地变量,当然重点还是稍显复杂的上下文管理部分。


本文并不涉及到它详细的原理,建议有兴趣者可以上它官网看看(不算很复杂),全中文的也好理解,并且还附有其执行时序图。


说明:它还支持javaagent完全零侵入方式接入,可以说是非常强大和好用的一个基础工具,值得使用明白,对中间件团队能提供良好的支持。


使用场景


官方流出了其四大使用场景:


  1. 分布式跟踪系统(链路追踪)
  2. 日志收集记录系统上下文(MDC)
  3. Session级Cache
  4. 应用容器或上层框架跨应用代码给下层SDK传递信息


其中场景1和场景2在全链路压测平台打造的时候都会触及到,所以基于TTL来解决这些问题不失外一个非常好的选择。


总结


ThreadLocal的一步步的进化,最终来到了TransmittableThreadLocal,它能够满足我们对线程间数据传递的几乎一切遐想,这对我们做类似于全链路压测这种平台的时候非常有帮助,期待成效。

相关文章
|
9月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
429 1
|
9月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
396 1
|
10月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
443 0
|
10月前
|
Java API 开发工具
【Azure Developer】Java代码实现获取Azure 资源的指标数据却报错 "invalid time interval input"
在使用 Java 调用虚拟机 API 获取指标数据时,因本地时区设置非 UTC,导致时间格式解析错误。解决方法是在代码中手动指定时区为 UTC,使用 `ZoneOffset.ofHours(0)` 并结合 `withOffsetSameInstant` 方法进行时区转换,从而避免因时区差异引发的时间格式问题。
423 4
|
10月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
617 16
|
存储 安全 Java
解锁Java并发编程奥秘:深入剖析Synchronized关键字的同步机制与实现原理,让多线程安全如磐石般稳固!
【8月更文挑战第4天】Java并发编程中,Synchronized关键字是确保多线程环境下数据一致性与线程安全的基础机制。它可通过修饰实例方法、静态方法或代码块来控制对共享资源的独占访问。Synchronized基于Java对象头中的监视器锁实现,通过MonitorEnter/MonitorExit指令管理锁的获取与释放。示例展示了如何使用Synchronized修饰方法以实现线程间的同步,避免数据竞争。掌握其原理对编写高效安全的多线程程序极为关键。
404 1
|
安全 Java 开发者
Java并发编程中的线程安全问题及解决方案探讨
在Java编程中,特别是在并发编程领域,线程安全问题是开发过程中常见且关键的挑战。本文将深入探讨Java中的线程安全性,分析常见的线程安全问题,并介绍相应的解决方案,帮助开发者更好地理解和应对并发环境下的挑战。【7月更文挑战第3天】
489 0
|
安全 Java 开发者
Java并发编程中的线程安全策略
在现代软件开发中,Java语言的并发编程特性使得多线程应用成为可能。然而,随着线程数量的增加,如何确保数据的一致性和系统的稳定性成为开发者面临的挑战。本文将探讨Java并发编程中实现线程安全的几种策略,包括同步机制、volatile关键字的使用、以及java.util.concurrent包提供的工具类,旨在为Java开发者提供一系列实用的方法来应对并发问题。
242 0
|
存储 安全 Java
深入理解Java并发编程:线程安全与锁机制
【5月更文挑战第31天】在Java并发编程中,线程安全和锁机制是两个核心概念。本文将深入探讨这两个概念,包括它们的定义、实现方式以及在实际开发中的应用。通过对线程安全和锁机制的深入理解,可以帮助我们更好地解决并发编程中的问题,提高程序的性能和稳定性。