如何解決異步線程導(dǎo)致的traceId為空的問題
更新時(shí)間:2025年02月07日 08:37:29 作者:從int開始
文章討論了在使用異步線程時(shí),traceId為空的問題,并提出了使用線程池的解決方案,作者分享了個(gè)人經(jīng)驗(yàn),并鼓勵(lì)大家參考和支持腳本之家
異步線程導(dǎo)致的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任務(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)存泄漏等問題,釋放資源)
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)文章
idea之Recompile、Rebuild和Build之間的區(qū)別及說明
這篇文章主要介紹了idea之Recompile、Rebuild和Build之間的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
Java關(guān)于List集合去重方案詳細(xì)介紹
實(shí)際項(xiàng)目開發(fā)中,很多業(yè)務(wù)場(chǎng)景下都會(huì)遇見集合去重。在說到List集合去重之前,首先我們回顧下普通類型的list如何去重2021-09-09
java實(shí)現(xiàn)微信公眾號(hào)消息推送的方法詳解
這篇文章主要為大家詳細(xì)介紹了如何利用java實(shí)現(xiàn)微信公眾號(hào)消息推送的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10
Java幾個(gè)實(shí)例帶你進(jìn)階升華下篇
與其明天開始,不如現(xiàn)在行動(dòng),本文為你帶來幾個(gè)Java書寫的實(shí)際案例,對(duì)鞏固編程的基礎(chǔ)能力很有幫助,快來一起往下看看吧2022-03-03
SpringBoot整合Echarts繪制靜態(tài)數(shù)據(jù)柱狀圖和餅圖
這篇文章給大家介紹了SpringBoot整合Echarts繪制靜態(tài)數(shù)據(jù)柱狀圖和餅圖,文中通過代碼示例給大家介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下2024-03-03
Java使用Jdbc連接Oracle執(zhí)行簡(jiǎn)單查詢操作示例
這篇文章主要介紹了Java使用Jdbc連接Oracle執(zhí)行簡(jiǎn)單查詢操作,結(jié)合實(shí)例形式詳細(xì)分析了java基于jdbc實(shí)現(xiàn)Oracle數(shù)據(jù)庫的連接與查詢相關(guān)操作技巧,需要的朋友可以參考下2019-09-09
Java實(shí)現(xiàn)為Word每一頁設(shè)置不同圖片水印的效果
Word中設(shè)置水印時(shí),可加載圖片設(shè)置為水印效果,但通常添加水印效果時(shí),會(huì)對(duì)所有頁面都設(shè)置成統(tǒng)一效果。所以本文為大家介紹了一個(gè)方法,可以實(shí)現(xiàn)對(duì)每一頁或者某個(gè)頁面設(shè)置不同的水印效果,需要的可以參考一下2022-02-02
SpringBoot參數(shù)驗(yàn)證的幾種方式小結(jié)
在日常的接口開發(fā)中,為了防止非法參數(shù)對(duì)業(yè)務(wù)造成影響,經(jīng)常需要對(duì)接口的參數(shù)進(jìn)行校驗(yàn),例如登錄的時(shí)候需要校驗(yàn)用戶名和密碼是否為空,所以本文介紹了SpringBoot參數(shù)驗(yàn)證的幾種方式,需要的朋友可以參考下2024-07-07

