• springBoot异步线程,父子线程数据传递的5种姿势


    背景

    在实际开发过程中我们需要父子之间传递一些数据,比如用户信息等。该文章从5种解决方案解决父子之间数据传递困扰

    姿势1:ThreadLocal+TaskDecorator

    用户工具类 UserUtils

    1. /**
    2. *使用ThreadLocal存储共享的数据变量,如登录的用户信息
    3. */
    4. public class UserUtils {
    5. private static final ThreadLocal userLocal=new ThreadLocal<>();
    6. public static String getUserId(){
    7. return userLocal.get();
    8. }
    9. public static void setUserId(String userId){
    10. userLocal.set(userId);
    11. }
    12. public static void clear(){
    13. userLocal.remove();
    14. }
    15. }
    16. 复制代码

    自定义CustomTaskDecorator

    1. /**
    2. * 线程池修饰类
    3. */
    4. public class CustomTaskDecorator implements TaskDecorator {
    5. @Override
    6. public Runnable decorate(Runnable runnable) {
    7. // 获取主线程中的请求信息(我们的用户信息也放在里面)
    8. String robotId = UserUtils.getUserId();
    9. System.out.println(robotId);
    10. return () -> {
    11. try {
    12. // 将主线程的请求信息,设置到子线程中
    13. UserUtils.setUserId(robotId);
    14. // 执行子线程,这一步不要忘了
    15. runnable.run();
    16. } finally {
    17. // 线程结束,清空这些信息,否则可能造成内存泄漏
    18. UserUtils.clear();
    19. }
    20. };
    21. }
    22. }
    23. 复制代码

    ExecutorConfig

    在原来的基础上增加 executor.setTaskDecorator(new CustomTaskDecorator());

    1. @Bean(name = "asyncServiceExecutor")
    2. public Executor asyncServiceExecutor() {
    3. log.info("start asyncServiceExecutor----------------");
    4. //ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    5. //使用可视化运行状态的线程池
    6. ThreadPoolTaskExecutor executor = new VisiableThreadPoolTaskExecutor();
    7. //配置核心线程数
    8. executor.setCorePoolSize(corePoolSize);
    9. //配置最大线程数
    10. executor.setMaxPoolSize(maxPoolSize);
    11. //配置队列大小
    12. executor.setQueueCapacity(queueCapacity);
    13. //配置线程池中的线程的名称前缀
    14. executor.setThreadNamePrefix(namePrefix);
    15. // rejection-policy:当pool已经达到max size的时候,如何处理新任务
    16. // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
    17. executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    18. //增加线程池修饰类
    19. executor.setTaskDecorator(new CustomTaskDecorator());
    20. //增加MDC的线程池修饰类
    21. //executor.setTaskDecorator(new MDCTaskDecorator());
    22. //执行初始化
    23. executor.initialize();
    24. log.info("end asyncServiceExecutor------------");
    25. return executor;
    26. }
    27. 复制代码

    AsyncServiceImpl

    1. /**
    2. * 使用ThreadLocal方式传递
    3. * 带有返回值
    4. * @throws InterruptedException
    5. */
    6. @Async("asyncServiceExecutor")
    7. public CompletableFuture<String> executeValueAsync2() throws InterruptedException {
    8. log.info("start executeValueAsync");
    9. System.out.println("异步线程执行返回结果......+");
    10. log.info("end executeValueAsync");
    11. return CompletableFuture.completedFuture(UserUtils.getUserId());
  • 相关阅读:
    Linux系统tcp连接设置
    基于Springboot外卖系统19:用户地址+默认收货地址
    【一起学Rust | 框架篇 | ws-rs框架】属于Rust的Websocket框架——ws-rs
    「数据结构详解·三」栈
    Android 复习string.xml中的替换符
    数据预处理&降维&主成分分析
    WEB前端 网页设计 简介
    Java基于springboot+vue的图书馆网上图书借阅系统 nodejs前后端分离
    【C++入门】友元函数详解(定义、实现、优缺点)
    小红书信息流广告投放怎么收费?投信息流广告效果怎么样
  • 原文地址:https://blog.csdn.net/java_beautiful/article/details/126889781