java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot集成自定义线程池和异常处理

SpringBoot集成自定义线程池和异常处理的两种方式

作者:Listen·Rain

这篇文章主要介绍了SpringBoot集成自定义线池,详解配置步骤、使用@Async注解实现异步调用,并讨论CompletableFuture异常处理及全局异常捕;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"),指定使用上述自定义线程池。

注意:

  1. 启动类需添加 @EnableAsync
  2. 异步方法必须在另一个类中调用(自调用无效),因为 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、关键注意事项

  1. 返回值类型:@Async 方法若需返回结果,必须返回 CompletableFuture<T>Future<T>,否则调用方无法获取返回值。
  2. 异常处理:异步方法中的异常不会直接抛出到 Controller。建议配置全局 AsyncUncaughtExceptionHandler 或在 CompletableFuture 链中处理。
  3. 事务问题:@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 容器

在配置类中重写 getAsyncExecutorgetAsyncUncaughtExceptionHandler 方法。

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,需在链式调用末尾添加 exceptionallyhandle,确保业务级异常被捕获。

future.thenApply(res -> process(res))
      .exceptionally(ex -> {
          log.error("业务处理失败", ex);
          return defaultResult; // 返回默认值,防止链路中断
      });

4、核心区别总结

场景异常捕获方式适用情况
@Async 无返回值AsyncUncaughtExceptionHandler简单通知、日志记录等“发了就不管”的场景。
CompletableFuture.exceptionally() / .handle()需要获取结果、进行业务补偿或降级的场景。
Controller 层@RestControllerAdvice无效。无法捕获异步线程抛出的异常。

以上就是SpringBoot集成自定义线程池和异常处理的两种方式的详细内容,更多关于SpringBoot集成自定义线程池和异常处理的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文