ThreadLocal InheritableThreadLocal TransmittableThreadLocal is simple to use

Requirements: The main thread transfers user token information to the asynchronous thread,

Several key objects about data transfer between threads,

  • When the main thread passes to the child thread, it can pass the InheritableThreadLocal object
  • When using ExecutorService or CompletableFuture to execute, the reason for thread reuse in the thread pool, and the value of inheritableThreadLocals in the Thread object is null, so the InheritableThreadLocal object cannot be used
  • TransmittableThreadLocal is a more suitable solution Official address
  • Asynchronous thread RequestContextHolder is empty problem

first example

public static final ThreadLocal<String> context = new ThreadLocal<>();//
public static final ThreadLocal<String> context1 = new TransmittableThreadLocal<>();//
public static final ThreadLocal<String> context2 = new InheritableThreadLocal<>();

public static void main(String[] args) {
    
    
        context.set("A");
        context1.set("B");
        context2.set("C");
        CompletableFuture.runAsync(() -> {
    
    //ThreadLocal 线程之间隔离
            String mm = context.get();
            log.info("1: {}",mm);
        });
        CompletableFuture.runAsync(TtlRunnable.get(() -> {
    
     //TransmittableThreadLocal可以取到
            String mm = context1.get();
            log.info("2: {}",mm);

        }));
        CompletableFuture.runAsync(() -> {
    
     //取不到
            String mm = context2.get();
            log.info("3: {}",mm);

        });
        Thread thread = new Thread(() -> {
    
     // 子线程,正常可以取到
            String mm = context2.get();
            log.info("4: {}",mm);
        });
        thread.start();
    }
[ForkJoinPool.commonPool-worker-1] INFO cn.me56.integration.stat.StatApiController - 1: null
[ForkJoinPool.commonPool-worker-2] INFO cn.me56.integration.stat.StatApiController - 2: A
[ForkJoinPool.commonPool-worker-1] INFO cn.me56.integration.stat.StatApiController - 3: null
[Thread-0] INFO cn.me56.integration.stat.StatApiController - 4: C

Here is an example of InheritableThreadLocal using child threads:

public class InheritableThreadLocalDemo {
    
    

    private static ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();

    public static void main(String[] args) {
    
    
        threadLocal.set("mainThread");
        System.out.println("value:"+threadLocal.get());
        Thread thread = new Thread(new Runnable() {
    
     //子线程,可以取到
            @Override
            public void run() {
    
    
                String value = threadLocal.get();
                System.out.println("value:"+value);
            }
        });
        thread.start();
    }

}
value:mainThread
value:mainThread

TransmittableThreadLocal, easy to use

public static final ThreadLocal<String> context1 = new TransmittableThreadLocal<>();//
CompletableFuture.runAsync(TtlRunnable.get(() -> {
    
     
	//do something...
}));
或者
CompletableFuture.supplyAsync(TtlWrappers.wrapSupplier(()-> {
    
    
	//do something...
	return "return value";
	}) );
或者
java agent 方式 

After the data can be passed between threads, let’s look at the problem that the RequestContextHolder is empty. Initially, I want to pass the request object to the asynchronous thread. After trying it, I feel that this solution is unreasonable, and there is no need to pass the entire request in.

  1. Use the following method. After setting, enter the asynchronous thread, and RequestContextHolder.getRequestAttributes() is still empty...
RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true);
  1. Use the following method as follows. After the main thread is closed, the child thread wants to get the parameters in the request, but it is still empty. If it is a copy of a request, it should be normal
CompletableFuture.runAsync(() -> {
    
     
	RequestContextHolder.setRequestAttributes(...);
	//do something...
});

In the end, because the business needs to be completed, it is hoped that the long-term statistics/query interface, in the case of limited system resources, will be divided into multiple subtasks by exchanging time for space, so here only MDC is used for parameter transfer between threads The .put/get method is simply realized

Guess you like

Origin blog.csdn.net/zoeou/article/details/127818532