README-EN.md
<p align="center"> <a href="https://github.com/alibaba/transmittable-thread-local/actions/workflows/ci.yaml"></a> <a href="https://github.com/alibaba/transmittable-thread-local/actions/workflows/strong_ci.yaml"></a> <a href="https://app.codecov.io/gh/alibaba/transmittable-thread-local/tree/master"></a> <a href="https://openjdk.java.net/"></a> <a href="https://www.apache.org/licenses/LICENSE-2.0.html"></a> <a href="https://alibaba.github.io/transmittable-thread-local/apidocs/"></a> <a href="https://repo1.maven.org/maven2/com/alibaba/transmittable-thread-local/maven-metadata.xml"></a> <a href="https://github.com/alibaba/transmittable-thread-local/releases"></a> <a href="https://github.com/alibaba/transmittable-thread-local/stargazers"></a> <a href="https://github.com/alibaba/transmittable-thread-local/fork"></a> <a href="https://github.com/alibaba/transmittable-thread-local/network/dependents"></a> <a href="https://github.com/alibaba/transmittable-thread-local/issues"></a> <a href="https://github.com/alibaba/transmittable-thread-local/graphs/contributors"></a> <a href="https://github.com/alibaba/transmittable-thread-local"></a> <a href="https://gitpod.io/#https://github.com/alibaba/transmittable-thread-local"></a> </p>[!IMPORTANT] 🚧 This branch is
TransmittableThreadLocal(TTL) v3, which is in development and has not been released yet.
See issue 432 for thev3notes, work item list and its progress.👉 The stable version
v2.xcurrently 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 6support, use version2.12.x<a href="https://repo1.maven.org/maven2/com/alibaba/transmittable-thread-local/maven-metadata.xml"></a>
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 CallableDecorate 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 ExecutorgetTtlExecutorService: decorate interface ExecutorServicegetTtlScheduledExecutorService: decorate interface ScheduledExecutorServiceSample 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:falseTTL agent arguments, see the javadoc of TtlAgent.java.Add start options on Java command:
-javaagent:path/to/transmittable-thread-local-2.x.y.jarJava 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),
you must add TTL agent jar to 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-PathA 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