异步场景下的ThreadLocal解决方案

kyaa111 3年前 ⋅ 847 阅读

引入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.12.1</version>
</dependency>

线程池配置

@Component
public class AsyncThreadPoolConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(5);
        threadPool.setMaxPoolSize(20);
        threadPool.setQueueCapacity(200);
        threadPool.setKeepAliveSeconds(60);
        threadPool.setThreadNamePrefix("MyThread: ");
        threadPool.initialize();
        return TtlExecutors.getTtlExecutor(threadPool);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

controller

@RestController
@RequestMapping
public class TestController {

    public static TransmittableThreadLocal<String> VAL = new TransmittableThreadLocal<>();

    @Autowired
    TestService testService;

    @GetMapping("/async")
    public String async() throws ExecutionException, InterruptedException {
        System.out.println("Controller Thread: " + Thread.currentThread().getName());

        VAL.set(new Date().toLocaleString());
        Future<String> test = testService.test();
        test.get();
        System.out.println("------------------------------------");
        return "";
    }
}

service

@Service
public class TestService {

    @Async
    public Future<String> test() {
        try {
            System.out.println("Service Thread: " + Thread.currentThread().getName());
            System.out.println("service get: " + TestController.VAL.get());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<>("yes");
    }

}

输出

Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 1
service get: 2021-4-15 17:35:26
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 2
service get: 2021-4-15 17:35:28
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 3
service get: 2021-4-15 17:35:30
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 4
service get: 2021-4-15 17:35:31
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 5
service get: 2021-4-15 17:35:33
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 1
service get: 2021-4-15 17:35:34
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 2
service get: 2021-4-15 17:35:38
------------------------------------

原理:

装饰者模式

对Runnable进行包装

装饰者模式