参考:https://mp.weixin.qq.com/s/3VmgxcoFazMMhnzU8ddnKQ
代码线程池配置@EnableAsync
@Configuration
public class ThreadPoolConfig {
@Bean(name = "asyncTaskExecutor")
public ThreadPoolTaskExecutor asyncTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//1: 核心线程数目
executor.setCorePoolSize(5);
//2: 指定最大线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
executor.setMaxPoolSize(10);
//3: 队列中最大的数目
executor.setQueueCapacity(200);
//4: 线程名称前缀
executor.setThreadNamePrefix("kap-Thread-");
//5:当pool已经达到max size的时候,如何处理新任务
// CallerRunsPolicy: 会在execute 方法的调用线程中运行被拒绝的任务,如果执行程序已关闭,则会丢弃该任务
// AbortPolicy: 抛出java.util.concurrent.RejectedExecutionException异常
// DiscardOldestPolicy: 抛弃旧的任务
// DiscardPolicy: 抛弃当前的任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//6: 线程空闲后的最大存活时间(默认值 60),当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
executor.setKeepAliveSeconds(60);
//7:线程空闲时间,当线程空闲时间达到keepAliveSeconds(秒)时,线程会退出,直到线程数量等于corePoolSize,如果allowCoreThreadTimeout=true,则会直到线程数量等于0
executor.setAllowCoreThreadTimeOut(false);
// 8.设置线程traceId
executor.setTaskDecorator(new MdcTaskDecorator());
//
executor.initialize();
return executor;
}
}
异步调用线程设置traceId
public class MdcTaskDecorator implements TaskDecorator{
@Override
public Runnable decorate(Runnable runnable) {
Map map = MDC.getCopyOfContextMap();
return () -> {
try{
MDC.setContextMap(map);
runnable.run();
} finally {
MDC.clear();
}
};
}
}
返回对象设置traceId
@Data @ApiModel(value = "接口返回对象", description = "接口返回对象") public class Result日志配置添加traceIdimplements Serializable { private static final long serialVersionUID = 1L; private static final String TRACE_ID = "TRACE_ID"; @ApiModelProperty(value = "成功标志") private boolean success = true; @ApiModelProperty(value = "返回处理消息") private String message = "操作成功!"; @ApiModelProperty(value = "返回代码") private Integer code = 0; @ApiModelProperty(value = "返回数据对象") private T result; private String traceId; @ApiModelProperty(value = "时间戳") private long timestamp = System.currentTimeMillis(); public Result() { this.traceId = MDC.get(TRACE_ID); } public static Result OK() { Result result = new Result (); result.setSuccess(true); result.setCode(1); result.setMessage("成功"); result.traceId = MDC.get(TRACE_ID); return result ; } }
测试案例采用shiro做安全框架%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{50}:%L) - [%X{TRACE_ID}] - %msg%n
在shiro的filter添加traceId
@Slf4j
public class JwtFilter extends BasicHttpAuthenticationFilter {
private static final String TRACE_ID = "TRACE_ID";
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader("access-token");
JwtToken jwtToken = new JwtToken(token);
// 提交给realm进行登录验证,如果错误会抛出异常并被捕获
getSubject(request, response).login(jwtToken);
//添加TRACE_ID
MDC.put(TRACE_ID, UUID.randomUUID().toString());
return true;
}
@Override
public void destroy() {
MDC.clear();
}
}
测试
@GetMapping("/getLeaderUserLists")
@ApiOperation(value = "查询领导人员列表", notes = "查询领导人员列表")
public Result> getLeaderUserList() {
QueryWrapper queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(UserInfoView::getUserIdentity, 2);
List list = userInfoViewService.list(queryWrapper);
//异步调用
CompletableFuture future =
CompletableFuture.runAsync(() -> {
sysUserService.getUserListLikeUserNameVoid("XX");
},executor);
return Result.OK(list);
}
结果



