SpringBoot集成自定义线程池和异常处理的两种方式
一.Spring Boot 集成自定义线程池
在 Spring Boot 中,通过 @Configuration 配置 Bean,并结合 @Async 注解或手动注入 ThreadPoolTaskExecutor,可实现声明式异步调用。
1、配置自定义线程池
创建配置类,定义 ThreadPoolTaskExecutor Bean,确保参数可控且线程命名规范。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class AsyncConfig {
@Bean("bizTaskExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("biz-async-");
// 拒绝策略:由调用线程执行,起到背压作用
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
2、使用 @Async 实现声明式异步
在 Service 层方法上添加 @Async("bizTaskExecutor"),指定使用上述自定义线程池。
注意:
- 启动类需添加
@EnableAsync。 - 异步方法必须在另一个类中调用(自调用无效),因为 Spring AOP 基于代理。
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class OrderService {
@Async("bizTaskExecutor")
public CompletableFuture<String> queryUserAsync() {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
return CompletableFuture.completedFuture("User_1001");
}
@Async("bizTaskExecutor")
public CompletableFuture<String> queryOrderAsync() {
try { Thread.sleep(1200); } catch (InterruptedException e) {}
return CompletableFuture.completedFuture("Order_List");
}
}
3、Controller 中编排异步结果
在 Controller 中注入 Service,利用 CompletableFuture 组合多个异步任务的结果。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/order/detail")
public String getOrderDetail() throws Exception {
// 并行发起两个异步请求
CompletableFuture<String> userFuture = orderService.queryUserAsync();
CompletableFuture<String> orderFuture = orderService.queryOrderAsync();
// 等待所有任务完成并合并结果
CompletableFuture.allOf(userFuture, orderFuture).join();
return "用户: " + userFuture.get() + ", 订单: " + orderFuture.get();
}
}
4、关键注意事项
- 返回值类型:
@Async方法若需返回结果,必须返回CompletableFuture<T>或Future<T>,否则调用方无法获取返回值。 - 异常处理:异步方法中的异常不会直接抛出到 Controller。建议配置全局
AsyncUncaughtExceptionHandler或在CompletableFuture链中处理。 - 事务问题:
@Async方法默认不在主事务中运行。若需事务,需在异步方法内部单独开启@Transactional。
二.Spring Boot 异步全局异常处理
在 Spring Boot 中,@Async 方法的异常无法被 Controller 的 @ExceptionHandler 捕获。需配置 AsyncUncaughtExceptionHandler 进行统一兜底,防止异常静默丢失。
1、自定义异常处理器
实现 AsyncUncaughtExceptionHandler 接口,记录日志或发送告警。
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
@Slf4j
public class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
log.error("异步任务异常 - 方法: {}, 参数: {}", method.getName(), params, ex);
// 此处可集成监控告警(如 Sentry/Prometheus)
}
}
2、注册到 Spring 容器
在配置类中重写 getAsyncExecutor 和 getAsyncUncaughtExceptionHandler 方法。
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("biz-async-");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new CustomAsyncExceptionHandler();
}
}
3、CompletableFuture 的异常处理
若使用 CompletableFuture,需在链式调用末尾添加 exceptionally 或 handle,确保业务级异常被捕获。
future.thenApply(res -> process(res))
.exceptionally(ex -> {
log.error("业务处理失败", ex);
return defaultResult; // 返回默认值,防止链路中断
});
4、核心区别总结
| 场景 | 异常捕获方式 | 适用情况 |
|---|---|---|
| @Async 无返回值 | AsyncUncaughtExceptionHandler | 简单通知、日志记录等“发了就不管”的场景。 |
| CompletableFuture | .exceptionally() / .handle() | 需要获取结果、进行业务补偿或降级的场景。 |
| Controller 层 | @RestControllerAdvice | 无效。无法捕获异步线程抛出的异常。 |
以上就是SpringBoot集成自定义线程池和异常处理的两种方式的详细内容,更多关于SpringBoot集成自定义线程池和异常处理的资料请关注脚本之家其它相关文章!
相关文章
用html css javascript打造自己的RIA图文教程
用html&css&javascript打造自己的RIA之一,包括了配置等2009-07-07


最新评论