This is Weihubeats. If you think the article is good, you can pay attention to the small playing technology of the public account. The article will be first published. No marketing numbers, no clickbait
Threads, parent threads, thread pools
We know that passing values between threads can be handled using the JDK’s built-in ThreadLocal, We can use the InheritableThreadLocal provided by the JDK if we encounter scenarios that require parent-child thread values to be passed, but many business scenarios actually need to pass the ThreadLocal values from the task submission to the thread pool to the task execution
Detailed introduction about InheritableThreadLocal refer to post before weihubeats.blog.csdn.net/article/det…
InheritableThreadLocal simple test
This is a bit confusing, so let’s take a quick look at a demo that uses an InheritableThreadLocal + thread pool
public class InheritableThreadLocalTest {
private static final AtomicInteger ID_SEQ = new AtomicInteger();
private static final ExecutorService THREAD_POOL = Executors.newFixedThreadPool(1, r -> new Thread(r, "thread-" + ID_SEQ.getAndIncrement()));
private static Integer i = 0;
private static final ThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();
public static void main(String[] args) throws Exception {
// Simulate an interface call
IntStream.range(0.10).forEach(InheritableThreadLocalTest::testInheritableThreadLocal);
THREAD_POOL.shutdown();
}
public static void testInheritableThreadLocal(int s) {
inheritableThreadLocal.set("Playing technique"+ i++); Future<? > submit = THREAD_POOL.submit(new ZouTask("Task" + s));
try {
submit.get();
} catch(Exception e) { e.printStackTrace(); }}public static class ZouTask implements Runnable{
String taskName;
public ZouTask(String taskName) {
this.taskName = taskName;
}
@Override
public void run(a) {
System.out.println(taskName + "Thread:" + Thread.currentThread().getName() + "Obtained value:"+ inheritableThreadLocal.get()); inheritableThreadLocal.remove(); }}Copy the code
Running results:
You can see that after we get the first value, we never get the second valueInheritableThreadLocal
The value of the. The correct result should look like this:Why did this happen? The reason is very simple,InheritableThreadLocal
Values are passed only when the child thread is created. The thread pool, on the other hand, will be reused after the thread is created, so it will not get the value later
TransmittableThreadLocal introduction
If there is any thread pool where there is TransmittableThreadLocal (if there is any thread pool where there is no context TransmittableThreadLocal), there is no context TransmittableThreadLocal (if there is any thread pool where there is no context TransmittableThreadLocal)
Making the address
Features (official website):
TransmittableThreadLocal(TTL) : provides the function of transmitting ThreadLocal values when the execution components of pooled and multiplexed threads such as thread pools are used to solve the problem of context transmission during asynchronous execution. A Java standard library this should provide the standard for the frame/middleware infrastructure development ability, the library function focus & 0, 17/16 support Java / 15/14/13/12/11/10/9/8/7/6.
The InheritableThreadLocal class in the JDK completes value passing from parent thread to child thread. But in the case of execution components that are pooled and reused by threads, such as thread pools, threads are created by thread pools and are pooled and reused; Parent-child ThreadLocal passes are meaningless. What the application really needs is to pass the ThreadLocal value from the time the task is submitted to the thread pool to the time the task is executed The core of the whole TransmittableThreadLocal library functions (user API and frame/middleware integration API, thread pool ExecutorService Wrapper/ForkJoinPool TimerTask and thread factory), Only ~1000 SLOC lines of code, very small
TransmittableThreadLocal use
Introduction of depend on
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.12.4</version>
</dependency>
Copy the code
Let’s go back to the example above
public class TransmittableThreadLocalTest {
private static final AtomicInteger ID_SEQ = new AtomicInteger();
private static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(1, r -> new Thread(r, "thread-" + ID_SEQ.getAndIncrement()));
private static final TransmittableThreadLocal<String> ttl = new TransmittableThreadLocal<>();
private static Integer i = 0;
public static void main(String[] args) throws Exception {
// Simulate an interface call
IntStream.range(0.10).forEach(TransmittableThreadLocalTest::testInheritableThreadLocal);
EXECUTOR.shutdown();
}
public static void testInheritableThreadLocal(int s) {
ttl.set("Playing technique"+ i++); Future<? > submit = EXECUTOR.submit(TtlRunnable.get(new ZouTask("Task" + s)));
try {
submit.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch(ExecutionException e) { e.printStackTrace(); }}public static class ZouTask implements Runnable{
String taskName;
public ZouTask(String taskName) {
this.taskName = taskName;
}
@Override
public void run(a) {
System.out.println(taskName + "Thread:" + Thread.currentThread().getName() + "Obtained value:"+ ttl.get()); ttl.remove(); }}}Copy the code
There are a few details:
- with
TransmittableThreadLocal
replaceInheritableThreadLocal
- with
TtlRunnable
Enhance the ORIGINAL JDKRunnable
interface
The usage of TransmittableThreadLocal is generally as follows. Some advanced uses may be such as non-intrusive Agent access
TransmittableThreadLocal is used in open source projects
TransmittableThreadLocal
It has been used in many open source projects
You can go and see for yourself
conclusion
The use of TransmittableThreadLocal ends here. Source code and principles related to the part of the interest can be studied, the official website also has some instructions, here will not explain for the time being