java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > 解决异步线程导致的traceId为空的问题

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

作者:从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 传进去即可

}

总结

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

您可能感兴趣的文章:
阅读全文