如何解决异步线程导致的traceId为空的问题

 更新时间:2025年02月07日 08:37:29   作者:从int开始  
文章讨论了在使用异步线程时,traceId为空的问题,并提出了使用线程池的解决方案,作者分享了个人经验,并鼓励大家参考和支持脚本之家

异步线程导致的traceId为空问题

1. 使用线程池

import lombok.Data;
import org.slf4j.MDC;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * xxx任务线程池配置
 */
@Configuration
@ConfigurationProperties(prefix = "thread-pool.x-xx")
@Data
public class XxxThreadPoolConfiguration {

  /**
   * Minimum number of threads to keep alive
   */
  private int corePoolSize = 8;

  /**
   * Maximum number of threads in the pool
   */
  private int maxPoolSize = 16;

  /**
   * Time in seconds to keep excess idle threads alive
   */
  private long keepAliveTime = 60;

  /**
   * queue size
   */
  private int queueSize = 1000;

  @Bean("xXxExecutor")
  public ThreadPoolExecutor xXxExecutor() {
    ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize,
            keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingQueue<>(queueSize));
    executor.setThreadFactory(runnable -> {
      Thread thread = new Thread(runnable);
      thread.setName("commonExecutor-" + thread.getId());
      return thread;
    });
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
    return executor;
  }



  public static class MdcThreadPoolExecutor extends ThreadPoolExecutor {

    public MdcThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
      super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
      // 在任务执行前,从当前线程(如果是主线程调用的话,就是主线程的MDC)获取traceId并设置到即将执行任务的线程的MDC中
      String traceId = MDC.get("traceId");
      MDC.put("traceId", traceId);
      super.beforeExecute(t, r);
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
      // 任务执行后清除MDC中的traceId(避免内存泄漏等问题,释放资源)
      MDC.remove("traceId");
      super.afterExecute(r, t);
    }
  }
}


2. 使用

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class XxxController{
// 构造器注入
  public OutChargeOrderPushController(
          @Qualifier("xXxExecutor")ThreadPoolExecutor executor
  ) {
    this.executor = executor;
  }
// 使用异步操作方法的时候把executor 传进去即可

}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • idea之Recompile、Rebuild和Build之间的区别及说明

    idea之Recompile、Rebuild和Build之间的区别及说明

    这篇文章主要介绍了idea之Recompile、Rebuild和Build之间的区别及说明,具有很好的参考价值,希望对有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • Java关于List集合去重方案详细介绍

    Java关于List集合去重方案详细介绍

    实际项目开发中,很多业务场景下都会遇见集合去重。在说到List集合去重之前,首先我们回顾下普通类型的list如何去重
    2021-09-09
  • java实现微信公众号消息推送的方法详解

    java实现微信公众号消息推送的方法详解

    这篇文章主要为大家详细介绍了如何利用java实现微信公众号消息推送的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-10-10
  • Java几个实例带你进阶升华下篇

    Java几个实例带你进阶升华下篇

    与其明天开始,不如现在行动,本文为你带来几个Java书写的实际案例,对巩固编程的基础能力很有帮助,快来一起往下看看吧
    2022-03-03
  • SpringBoot整合Echarts绘制静态数据柱状图和饼图

    SpringBoot整合Echarts绘制静态数据柱状图和饼图

    这篇文章给大家介绍了SpringBoot整合Echarts绘制静态数据柱状图和饼图,文中通过代码示例给大家介绍的非常详细,具有一定的参考价值,需要的朋友可以参考下
    2024-03-03
  • Java使用Jdbc连接Oracle执行简单查询操作示例

    Java使用Jdbc连接Oracle执行简单查询操作示例

    这篇文章主要介绍了Java使用Jdbc连接Oracle执行简单查询操作,结合实例形式详细分析了java基于jdbc实现Oracle数据库的连接与查询相关操作技巧,需要的朋友可以参考下
    2019-09-09
  • SpringBoot中@Import注解的使用方式

    SpringBoot中@Import注解的使用方式

    这篇文章主要介绍了SpringBoot中@Import注解的使用方式,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-05-05
  • Java实现为Word每一页设置不同图片水印的效果

    Java实现为Word每一页设置不同图片水印的效果

    Word中设置水印时,可加载图片设置为水印效果,但通常添加水印效果时,会对所有页面都设置成统一效果。所以本文为大家介绍了一个方法,可以实现对每一页或者某个页面设置不同的水印效果,需要的可以参考一下
    2022-02-02
  • Java装饰者模式的示例详解

    Java装饰者模式的示例详解

    装饰者模式:在不改变原有对象的基础之上,动态的将功能附加到对象上,提供了继承更有弹性的替代方案,也体现了开闭原则。本文将通过示例详细讲解一下装饰者模式,需要的可以参考一下
    2022-02-02
  • SpringBoot参数验证的几种方式小结

    SpringBoot参数验证的几种方式小结

    在日常的接口开发中,为了防止非法参数对业务造成影响,经常需要对接口的参数进行校验,例如登录的时候需要校验用户名和密码是否为空,所以本文介绍了SpringBoot参数验证的几种方式,需要的朋友可以参考下
    2024-07-07

最新评论