👉 Transmit multi-thread context, even using thread cached components like thread pool.
Class java.lang.InheritableThreadLocal
in JDK
can transmit context to child thread from parent thread.
But when use thread pool, thread is cached up and used repeatedly. Transmitting context from parent thread to child thread has no meaning. Application need transmit context from the time task is created to the time task is executed.
If you have problem or question,
- submit Issue
- mail list (Powered by nabble)
- Click "Options > Subscribe via email" to subscribe to this mailing list;
- Click "Options > Post by email..." to get the email address of this mailing list;
- You can post messages via email or through the forum interface.
The Requirements listed below is also why I sort out MTC
in my work.
- Application container or high layer framework transmit information to low layer sdk.
- Transmit context to logging without application code aware.
- simple usage
// set in parent thread
MtContextThreadLocal<String> parent = new MtContextThreadLocal<String>();
parent.set("value-set-in-parent");
// =====================================================
// read in child thread, value is "value-set-in-parent"
String value = parent.get();
This is the function of class java.lang.InheritableThreadLocal
, should use class java.lang.InheritableThreadLocal
instead.
But when use thread pool, thread is cached up and used repeatedly. Transmitting context from parent thread to child thread has no meaning. Application need transmit context from the time task is created to the point task is executed.
The solution is below usage.
- Transmit context even using thread pool
Decorate input Runnable
and Callable
by com.alibaba.mtc.MtContextRunnable
and com.alibaba.mtc.MtContextCallable
.
Sample code:
MtContextThreadLocal<String> parent = new MtContextThreadLocal<String>();
parent.set("value-set-in-parent");
Runnable task = new Task("1");
// extra work, create decorated mtContextRunnable object
Runnable mtContextRunnable = MtContextRunnable.get(task);
executorService.submit(mtContextRunnable);
// =====================================================
// read in task, value is "value-set-in-parent"
String value = parent.get();
above code show how to dealing with Runnable
, Callable
is similar:
MtContextThreadLocal<String> parent = new MtContextThreadLocal<String>();
parent.set("value-set-in-parent");
Callable call = new Call("1");
// extra work, create decorated mtContextCallable object
Callable mtContextCallable = MtContextCallable.get(call);
executorService.submit(mtContextCallable);
// =====================================================
// read in call, value is "value-set-in-parent"
String value = parent.get();
Eliminating the work of Runnable
and Callable
Decoration every time it is submitted to thread pool. This work can completed in the thread pool.
Use util class
com.alibaba.mtc.threadpool.MtContextExecutors
to decorate thread pool.
Util class com.alibaba.mtc.threadpool.MtContextExecutors
has below methods:
getMtcExecutor
: decorate interfaceExecutor
getMtcExecutorService
: decorate interfaceExecutorService
ScheduledExecutorService
: decorate interfaceScheduledExecutorService
Sample code:
ExecutorService executorService = ...
// extra work, create decorated executorService object
executorService = MtContextExecutors.getMtcExecutorService(executorService);
MtContextThreadLocal<String> parent = new MtContextThreadLocal<String>();
parent.set("value-set-in-parent");
Runnable task = new Task("1");
Callable call = new Call("2");
executorService.submit(task);
executorService.submit(call);
// =====================================================
// read in Task or Callable, value is "value-set-in-parent"
String value = parent.get();
In this usage, MtContext
transmission is transparent(no decoration operation).
Sample code:
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable task = new Task("1");
Callable call = new Call("2");
executorService.submit(task);
executorService.submit(call);
// =====================================================
// Task或是Call中可以读取, 值是"value-set-in-parent"
String value = parent.get();
See demo AgentDemo.java
.
Agent decorate 2 thread pool implementation classes
(implementation code MtContextTransformer.java
):
java.util.concurrent.ThreadPoolExecutor
java.util.concurrent.ScheduledThreadPoolExecutor
Add start options on Java command:
-Xbootclasspath/a:/path/to/multithread.context-x.y.z.jar:/path/to/javassist-3.12.1.GA.jar
-javaagent:/path/to/multithread.context-x.y.z.jar
NOTE:
- Agent modify the jdk classes, add code refer to the class of
MTC
, so the jar ofMTC Agent
should add tobootclasspath
. MTC Agent
modify the class byjavassist
, so the Jar ofjavassist
should add tobootclasspath
too.
Java command example:
java -Xbootclasspath/a:dependency/javassist-3.12.1.GA.jar:multithread.context-1.0.0.jar \
-javaagent:multithread.context-0.9.0-SNAPSHOT.jar \
-cp classes \
com.alibaba.mtc.threadpool.agent.AgentDemo
Run the script run-agent-demo.sh
to start demo of "Use Java Agent to decorate thread pool implementation class".
The current version Java API documentation: http://alibaba.github.io/multi-thread-context/apidocs/
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>multithread.context</artifactId>
<version>1.0.3</version>
</dependency>
Check available version at search.maven.org.