[!IMPORTANT] 🚧 This branch is
TransmittableThreadLocal(TTL) v3
, which is in development and has not been released yet. See issue 432 for thev3
notes, work item list and its progress.👉 The stable version
v2.x
currently in use is on branch2.x
.
📖 English Documentation | 📖 中文文档
👉 TransmittableThreadLocal
(TTL
): The missing Java™ std lib(simple & 0-dependency) for framework/middleware,
provide an enhanced InheritableThreadLocal
that transmits values between threads even using thread pooling components. Support Java 6~21
.
Class InheritableThreadLocal
in JDK
can transmit value to child thread from parent thread.
But when use thread pool, thread is cached up and used repeatedly. Transmitting value from parent thread to child thread has no meaning. Application need transmit value from the time task is created to the time task is executed.
If you have problem or question, please submit Issue or play fork and pull request dance.
[!NOTE] From
TTL v2.13+
upgrade toJava 8
. 🚀 If you needJava 6
support, use version2.12.x
The Requirements listed below is also why I sort out TransmittableThreadLocal
in my work.
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// =====================================================
// set in parent thread
context.set("value-set-in-parent");
// =====================================================
// read in child thread, value is "value-set-in-parent"
String value = context.get();
# See the executable demo SimpleDemo.kt
with full source code.
This is the function of class InheritableThreadLocal
, should use class InheritableThreadLocal
instead.
But when use thread pool, thread is cached up and used repeatedly. Transmitting value from parent thread to child thread has no meaning. Application need transmit value from the time task is created to the point task is executed.
The solution is below usage.
Runnable
and Callable
Decorate input Runnable
and Callable
by TtlRunnable
and TtlCallable
.
Sample code:
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// =====================================================
// set in parent thread
context.set("value-set-in-parent");
Runnable task = new RunnableTask();
// extra work, create decorated ttlRunnable object
Runnable ttlRunnable = TtlRunnable.get(task);
executorService.submit(ttlRunnable);
// =====================================================
// read in task, value is "value-set-in-parent"
String value = context.get();
NOTE:
Even when the same Runnable
task is submitted to the thread pool multiple times, the decoration operations(ie: TtlRunnable.get(task)
) is required for each submission to capture the value of the TransmittableThreadLocal
context at submission time; That is, if the same task is submitted next time without reperforming decoration and still using the last TtlRunnable
, the submitted task will run in the context of the last captured context. The sample code is as follows:
// first submission
Runnable task = new RunnableTask();
executorService.submit(TtlRunnable.get(task));
// ... some biz logic,
// and modified TransmittableThreadLocal context ...
context.set("value-modified-in-parent");
// next submission
// reperform decoration to transmit the modified TransmittableThreadLocal context
executorService.submit(TtlRunnable.get(task));
Above code show how to dealing with Runnable
, Callable
is similar:
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// =====================================================
// set in parent thread
context.set("value-set-in-parent");
Callable call = new CallableTask();
// extra work, create decorated ttlCallable object
Callable ttlCallable = TtlCallable.get(call);
executorService.submit(ttlCallable);
// =====================================================
// read in call, value is "value-set-in-parent"
String value = context.get();
# See the executable demo TtlWrapperDemo.kt
with full source code.
Eliminating the work of Runnable
and Callable
Decoration every time it is submitted to thread pool. This work can be completed in the thread pool.
Use util class
TtlExecutors
to decorate thread pool.
Util class TtlExecutors
has below methods:
getTtlExecutor
: decorate interface Executor
getTtlExecutorService
: decorate interface ExecutorService
getTtlScheduledExecutorService
: decorate interface ScheduledExecutorService
Sample code:
ExecutorService executorService = ...
// extra work, create decorated executorService object
executorService = TtlExecutors.getTtlExecutorService(executorService);
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
// =====================================================
// set in parent thread
context.set("value-set-in-parent");
Runnable task = new RunnableTask();
Callable call = new CallableTask();
executorService.submit(task);
executorService.submit(call);
// =====================================================
// read in Task or Callable, value is "value-set-in-parent"
String value = context.get();
# See the executable demo TtlExecutorWrapperDemo.kt
with full source code.
In this usage, transmittance is transparent(no decoration operation).
Sample code:
// ## 1. upper layer logic of framework ##
TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();
context.set("value-set-in-parent");
// ## 2. biz logic ##
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable task = new RunnableTask();
Callable call = new CallableTask();
executorService.submit(task);
executorService.submit(call);
// ## 3. underlayer logic of framework ##
// read in Task or Callable, value is "value-set-in-parent"
String value = context.get();
# See the executable demo AgentDemo.kt
with full source code, run demo by the script scripts/run-agent-demo.sh
.
At present, TTL
agent has decorated below JDK
execution components(aka. thread pool) implementation:
java.util.concurrent.ThreadPoolExecutor
and java.util.concurrent.ScheduledThreadPoolExecutor
JdkExecutorTtlTransformlet.java
.java.util.concurrent.ForkJoinTask
(corresponding execution component is java.util.concurrent.ForkJoinPool
)
ForkJoinTtlTransformlet.java
, supports since version 2.5.1
.CompletableFuture
and (parallel) Stream
introduced in Java 8 is executed through ForkJoinPool
underneath, so after supporting ForkJoinPool
, TTL
also supports CompletableFuture
and Stream
transparently. 🎉java.util.TimerTask
(corresponding execution component is java.util.Timer
)
TimerTaskTtlTransformlet.java
, supports since version 2.7.0
.2.11.2
decoration for TimerTask
default is enable (because correctness is first concern, not the best practice like "It is not recommended to use TimerTask
" :); before version 2.11.1
default is disable.ttl.agent.enable.timer.task
:
-javaagent:path/to/transmittable-thread-local-2.x.y.jar=ttl.agent.enable.timer.task:true
-javaagent:path/to/transmittable-thread-local-2.x.y.jar=ttl.agent.enable.timer.task:false
TTL
agent arguments, see the javadoc of TtlAgent.java
.Add start options on Java command:
-javaagent:path/to/transmittable-thread-local-2.x.y.jar
Java command example:
java -javaagent:transmittable-thread-local-2.x.y.jar \
-cp classes \
com.alibaba.demo.ttl.agent.AgentDemo
# if changed the TTL jar file name or the TTL version is before 2.6.0,
# should set argument -Xbootclasspath explicitly.
java -javaagent:path/to/ttl-foo-name-changed.jar \
-Xbootclasspath/a:path/to/ttl-foo-name-changed.jar \
-cp classes \
com.alibaba.demo.ttl.agent.AgentDemo
java -javaagent:path/to/transmittable-thread-local-2.5.1.jar \
-Xbootclasspath/a:path/to/transmittable-thread-local-2.5.1.jar \
-cp classes \
com.alibaba.demo.ttl.agent.AgentDemo
Run the script scripts/run-agent-demo.sh
to start demo of "Use Java Agent to decorate thread pool implementation class".
NOTE:
JDK
std lib classes, make code refer from std lib class to the TTL classes, so the TTL Agent jar must be added to boot classpath
.v2.6.0
, TTL agent jar will auto add self to boot classpath
. But you should NOT modify the downloaded TTL jar file name in the maven repo(eg: transmittable-thread-local-2.x.y.jar
).
ttl-foo-name-changed.jar
),boot classpath
manually by java option -Xbootclasspath/a:path/to/ttl-foo-name-changed.jar
.The implementation of auto adding self agent jar to boot classpath
use the Boot-Class-Path
property of manifest file(META-INF/MANIFEST.MF
) in the TTL Java Agent Jar:
[!NOTE]
Boot-Class-Path
A list of paths to be searched by the bootstrap class loader. Paths represent directories or libraries (commonly referred to as JAR or zip libraries on many platforms). These paths are searched by the bootstrap class loader after the platform specific mechanisms of locating a class have failed. Paths are searched in the order listed.
More info:
Java Agent Specification
- JavaDoc
文档The current version Java API documentation: https://alibaba.github.io/transmittable-thread-local/apidocs/
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.14.4</version>
</dependency>
Check available version at maven.org.
Compilation/build environment require JDK 8+
; Compilation can be performed in the normal way of Maven
.
# The project already contains Maven
that satisfied the required version, directly run mvnw
in the project root directory; there is no need to manually install Maven
by yourself.
# Run test case
./mvnw test
# Compile and package
./mvnw package
# Run test case, compile and package, install TTL library to local Maven
./mvnw install
##################################################
# If you use maven installed by yourself, the version requirement: maven 3.3.9+
mvn install
Some open-source projects used TTL
:
sofastack/sofa-rpc
trpc-group/trpc-java
tencentmusic/supersonic
dromara/hmily
dromara/gobrs-async
dromara/dynamic-tp
opengoofy/hippo4j
siaorg/sia-gateway
huaweicloud/Sermant
ZTO-Express/zms
lxchinesszz/tomato
ytyht226/taskflow
foldright/cffu
tuya/connector
apache/shardingsphere
apache/kylin
mybatis-flex/mybatis-flex
basicai/xtreme1
oceanbase/odc
sagframe/sagacity-sqltoy
dromara/stream-query
luo-zhan/Transformer
SimonAlong/Neo
ppdaicorp/das
didi/ALITA
didi/daedalus
dromara/liteflow
alibaba/bulbasaur
dromara/TLog
fayechenlong/plumelog
minbox-projects/minbox-logging
minbox-projects/api-boot
ofpay/logback-mdc-ttl
oldratlee/log4j2-ttl-thread-context-map
ymm-tech/easy-byte-coder
OpenBankProject/OBP-API
gz-yami/mall4j
Joolun/JooLun-wx
HummerRisk/HummerRisk
XiaoMi/mone
Mone
以微服务为核心的一站式企业协同研发平台。支持公共云、专有云和混合云多种部署形态;提供从“项目创建->开发->部署->治理->应用观测”端到端的研发全流程服务;通过云原生新技术和研发新模式,打造“双敏”,敏捷研发和敏捷组织,保障小米-中国区高复杂业务、大规模团队的敏捷研发协同,实现多倍效能提升。yangzongzhuan/RuoYi-Cloud
somowhere/albedo
qwdigital/LinkWechat
fushengqian/fuint
hiparker/opsli-boot
topiam/eiam
Newspiral/newspiral-business
ssssssss-team/spider-flow
nekolr/slime
Jackson0714/PassJava-Platform
martin-chips/DimpleBlog
SpringBoot2
搭建的个人博客系统zjcscut/octopus
xggz/mqr
alibaba/jvm-sandbox-repeater
vivo/MoonBox
alibaba/testable-mock
shulieTech/Takin
shulieTech/LinkAgent
alibaba/virtual-environment
Kubernetes
版实现Spring Cloud
/Spring Boot
microservices framework solution or scaffold
YunaiV/ruoyi-vue-pro
YunaiV/yudao-cloud
zlt2000/microservices-platform
dromara/lamp-cloud
zuihou/lamp-util
matevip/matecloud
gavenwangcn/vole
liuweijw/fw-cloud-framework
liuht777/Taroco
mingyang66/spring-parent
budwk/budwk
BudWk
原名 NutzWk
,基于国产框架 nutz 及 nutzboot 开发的开源Web基础项目,集权限体系、系统参数、数据字典、站内消息、定时任务、CMS、微信等最常用功能,不庞杂、不面面俱到,使其具有上手容易、开发便捷、扩展灵活等特性,特别适合各类大中小型定制化项目需求yinjihuan/spring-cloud
louyanfeng25/ddd-demo
nageoffer/12306
more open-source projects used TTL
, see
sofastack/sofa-rpc
trpc-group/trpc-java
tencentmusic/supersonic
dromara/hmily
dromara/gobrs-async
dromara/dynamic-tp
opengoofy/hippo4j
siaorg/sia-gateway
huaweicloud/Sermant
ZTO-Express/zms
lxchinesszz/tomato
ytyht226/taskflow
foldright/cffu
tuya/connector
apache/shardingsphere
apache/kylin
mybatis-flex/mybatis-flex
basicai/xtreme1
oceanbase/odc
sagframe/sagacity-sqltoy
dromara/stream-query
luo-zhan/Transformer
SimonAlong/Neo
ppdaicorp/das
didi/ALITA
didi/daedalus
dromara/liteflow
alibaba/bulbasaur
dromara/TLog
fayechenlong/plumelog
minbox-projects/minbox-logging
minbox-projects/api-boot
ofpay/logback-mdc-ttl
oldratlee/log4j2-ttl-thread-context-map
ymm-tech/easy-byte-coder
OpenBankProject/OBP-API
gz-yami/mall4j
Joolun/JooLun-wx
HummerRisk/HummerRisk
XiaoMi/mone
yangzongzhuan/RuoYi-Cloud
somowhere/albedo
qwdigital/LinkWechat
fushengqian/fuint
hiparker/opsli-boot
topiam/eiam
Newspiral/newspiral-business
ssssssss-team/spider-flow
nekolr/slime
Jackson0714/PassJava-Platform
martin-chips/DimpleBlog
zjcscut/octopus
xggz/mqr
alibaba/jvm-sandbox-repeater
vivo/MoonBox
alibaba/testable-mock
shulieTech/Takin
shulieTech/LinkAgent
alibaba/virtual-environment
YunaiV/ruoyi-vue-pro
YunaiV/yudao-cloud
zlt2000/microservices-platform
dromara/lamp-cloud
zuihou/lamp-util
matevip/matecloud
gavenwangcn/vole
liuweijw/fw-cloud-framework
liuht777/Taroco
mingyang66/spring-parent
budwk/budwk
NutzWk
yinjihuan/spring-cloud
louyanfeng25/ddd-demo
nageoffer/12306