如何解決異步線程導(dǎo)致的traceId為空的問(wèn)題
更新時(shí)間:2025年02月07日 08:37:29 作者:從int開始
文章討論了在使用異步線程時(shí),traceId為空的問(wèn)題,并提出了使用線程池的解決方案,作者分享了個(gè)人經(jīng)驗(yàn),并鼓勵(lì)大家參考和支持腳本之家
異步線程導(dǎo)致的traceId為空問(wèn)題
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任務(wù)線程池配置
*/
@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) {
// 在任務(wù)執(zhí)行前,從當(dāng)前線程(如果是主線程調(diào)用的話,就是主線程的MDC)獲取traceId并設(shè)置到即將執(zhí)行任務(wù)的線程的MDC中
String traceId = MDC.get("traceId");
MDC.put("traceId", traceId);
super.beforeExecute(t, r);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
// 任務(wù)執(zhí)行后清除MDC中的traceId(避免內(nèi)存泄漏等問(wèn)題,釋放資源)
MDC.remove("traceId");
super.afterExecute(r, t);
}
}
}
2. 使用
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class XxxController{
// 構(gòu)造器注入
public OutChargeOrderPushController(
@Qualifier("xXxExecutor")ThreadPoolExecutor executor
) {
this.executor = executor;
}
// 使用異步操作方法的時(shí)候把executor 傳進(jìn)去即可
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java開發(fā)推薦使用的JDK版本以及對(duì)比詳細(xì)分析
這篇文章詳細(xì)分析了JDK17和JDK21作為當(dāng)前推薦版本的優(yōu)缺點(diǎn),并對(duì)比了它們與JDK8和JDK11的差異,文中介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2025-04-04
Java實(shí)現(xiàn)整合文件上傳到FastDFS的方法詳細(xì)
FastDFS是一個(gè)開源的輕量級(jí)分布式文件系統(tǒng),對(duì)文件進(jìn)行管理,功能包括:文件存儲(chǔ)、文件同步、文件上傳、文件下載等,解決了大容量存儲(chǔ)和負(fù)載均衡的問(wèn)題。本文將提供Java將文件上傳至FastDFS的示例代碼,需要的參考一下2022-02-02
SpringBoot集成Druid實(shí)現(xiàn)監(jiān)控功能的示例代碼
這篇文章主要介紹了SpringBoot集成Druid實(shí)現(xiàn)監(jiān)控功能,Druid是阿里巴巴開發(fā)的號(hào)稱為監(jiān)控而生的數(shù)據(jù)庫(kù)連接池,可以很好的監(jiān)控DB池連接和SQL的執(zhí)行情況,天生就是針對(duì)監(jiān)控而生的DB連接池,文中通過(guò)代碼示例講解非常詳細(xì),需要的朋友可以參考下2024-02-02
JVM教程之Java代碼編譯和執(zhí)行的整個(gè)過(guò)程(二)
這篇文章主要介紹了JVM學(xué)習(xí)筆記第二篇,關(guān)于Java代碼編譯和執(zhí)行的整個(gè)過(guò)程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
spring cloud gateway轉(zhuǎn)發(fā)服務(wù)報(bào)錯(cuò)的解決
這篇文章主要介紹了spring cloud gateway轉(zhuǎn)發(fā)服務(wù)報(bào)錯(cuò)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09

