1、原理
TransmittableThreadLocal(简称TTL)是阿里巴巴开源的一个Java库,用于解决线程池中线程本地变量传递的问题。其底层原理主要是基于Java的ThreadLocal
机制并对其进行扩展,以支持在父子线程间以及线程池中任务切换时,能够传递和继承ThreadLocal
变量的值。下面是TTL的核心工作原理:
-
基于ThreadLocal的扩展: TTL继承自
InheritableThreadLocal和
ThreadLocal,
但与InheritableThreadLocal
不同的是,TTL解决了在已经存在的线程(如线程池中的线程)之间传递ThreadLocal
值的问题。 -
线程池任务切换处理:
- 在任务提交到线程池之前,会先将当前(父)线程的
ThreadLocal
变量值保存到一个中间结构中(通常是通过装饰器模式,比如TtlRunnable
或TtlCallable
)。 - 当任务开始在子线程(线程池中的线程)中执行时,会从这个中间结构中恢复这些变量值,并设置到子线程的
ThreadLocal
副本中,从而实现了值的跨线程传递。
- 在任务提交到线程池之前,会先将当前(父)线程的
-
异步任务传递: 对于异步任务,TTL确保了即使在异步执行的上下文中,父线程的
ThreadLocal
状态也能被正确地传递给处理该任务的子线程。 -
核心组件与流程:
- 构建TtlRunnable/Callable:TTL提供工具方法(如
TtlRunnable.get()
)来包装原有的Runnable
或Callable
对象,使其在执行前能加载父线程的ThreadLocal
状态。 - 上下文传递与清理:TTL管理一个上下文,其中包含要传递的
ThreadLocal
变量值,确保在任务执行前后,这些值的传递和清理操作得以正确执行,避免内存泄漏。
- 构建TtlRunnable/Callable:TTL提供工具方法(如
-
源码层面: TTL内部实现涉及对
ThreadLocal
的深入理解和扩展,包括如何安全地存储和恢复变量值,以及如何与线程池的任务调度机制相结合。它通过覆盖InheritableThreadLocal
的一些方法,并添加额外的逻辑来实现这一功能。
综上所述,TransmittableThreadLocal通过精心设计的机制,在不改变原有线程池和任务执行模型的基础上,增强了ThreadLocal
的传递能力,使之适应更复杂的多线程和线程池应用场景。
2、过程分析
上图其实把过程介绍的很清晰和详细了。我们可以简单的认为TransmittableThreadLocal和普通TheadLocal是一样的,都是线程变量,只不过从语义上TransmittableThreadLocal是用来在线程间传递值的。这个传递是TtlRunnable来完成的,它的本质是个wapper,它在执行线程前获取父线程的所有值(上图4.1),线程执行时会将这些值重放/赋值到子线程的里(上图6.2),当然TtlRunnable使用了工具类Transmitter。
因此TransmittableThreadLocal变量值要想实现线程间的传递,线程必须用TtlRunnable修饰,或者把线程提交给TtlExecutors修饰过的线程池执行,否则TransmittableThreadLocal与ThreadLocal没有区别。TtlExecutors的原理也很简单,它把提交给它的Runnable包装成TtlRunnable,我们看到TtlRunnable构造方法就是需要一个Runnable,当然如果提交给它的已经是TtlRunnable,它不会再次包装。
总结:TransmittableThreadLocal+TtlRunnable+TtlExecutors 是在Java提供的既有能力上进行包装、拓展,实现了新的功能,它使用了装饰器模式。