使用版本:release - v2.11.5
最近在准备双十一压测相关的调整工作,需要将线程池改为都使用TTL包装过的,用于辅助pinpoint插件实现Trace信息传递。之前没怎么关注过TTL这个库,因此在改用TTL的同时,学习下其实现原理。
一、背景
InheritableThreadLocal及其局限性
Jdk提供了InheritableThreadLocal类,用于在父子线程间传递线程变量(ThreadLocal),实现原理就是在Thread类保存名为inheritableThreadLocals的成员属性(以InheritableThreadLocal对象为Key的ThreadLocalMap),并在初始化创建子线程时,将父线程的inheritableThreadLocals赋给子线程,这部分逻辑在Thread.init()方法内。
这种方式在线程只被创建和使用一次时是有效的,但对于使用线程池的场景下,由于线程被复用,初始化一次后,后续使用并不会走这个ThreadLocal传递的流程,导致后续提交的任务并不会继承到父线程的线程变量,同时,还会获取到当前任务线程被之前几次任务所修改变量值。
二、TTL介绍
TransmittableThreadLocal(TTL)是阿里开源的,用于解决异步执行时上下文传递的问题的组件,在InheritableThreadLocal基础上,实现了线程复用场景下的线程变量传递功能。
主要使用方式:
1.直接使用
同ThreadLocal:父线程使用TransmittableThreadLocal保存变量,子线程get取出。
2.提交线程池使用