1、配置文件中添加如下配置
# 业务异步线程池配置
biz:
async:
executor:
corePoolSize: 2
maxPoolSize: 8
queueCapacity: 100
keepAliveSeconds: 60
threadNamePrefix: ${spring.application.name}
2、自定义任务线程池装饰器,用于在异步线程中传递MDC,异步方法中记录traceId
import org.slf4j.MDC;
import org.springframework.core.task.TaskDecorator;
import java.util.Map;
/**
* @ Author: cm
* @ Date: 2025-04-29-15:33
* @ Description: 自定义任务线程池装饰器,用于在异步线程中传递MDC,异步方法中记录traceId
*/
public class MdcTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
Map<String, String> contextMap = MDC.getCopyOfContextMap(); // 获取主线程 MDC
return () -> {
if (contextMap != null) {
MDC.setContextMap(contextMap); // 设置子线程 MDC
}
try {
runnable.run(); // 执行实际任务
} finally {
MDC.clear(); // 避免内存泄漏
}
};
}
}
3、异步线程配置类
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @ Date: 2025-04-29-14:17
* @ Description: 业务异步方法线程配置
*/
@Slf4j
@Data
@Configuration
@EnableAsync
@ConfigurationProperties(prefix = "biz.async.executor")
public class AsyncConfig implements AsyncConfigurer {
private int corePoolSize;
private int maxPoolSize;
private int queueCapacity;
private int keepAliveSeconds;
private String threadNamePrefix;
public static final String BIZ_PREFIX = "_biz-async-task-";
@Bean("bizAsyncTaskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize); // 核心线程数
executor.setMaxPoolSize(maxPoolSize); // 最大线程数
executor.setQueueCapacity(queueCapacity); // 队列容量
executor.setKeepAliveSeconds(keepAliveSeconds); // 空闲线程存活时间
executor.setThreadNamePrefix(threadNamePrefix + BIZ_PREFIX); // 线程名前缀
executor.setTaskDecorator(new MdcTaskDecorator()); // 设置线程池装饰器用于在异步任务中传递traceId
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略
executor.initialize();
return executor;
}
@Override
public Executor getAsyncExecutor() {
return taskExecutor();
}
/**
* 来处理 @Async 抛出的未捕获异常(仅用于无返回值的方法)
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (ex, method, params) -> {
log.error("业务异步方法异常, method:{}, params:{}", method, params, ex);
};
}
}
4.使用
@Async("bizAsyncTaskExecutor")
public void testAsync(){
log.info("测试打印日志"); //这里日志会带上traceId
}

5036

被折叠的 条评论
为什么被折叠?



