Spring @Async 默认使用不复用线程的 SimpleAsyncTaskExecutor,实际项目须自定义 ThreadPoolTaskExecutor Bean,配置核心/最大线程数、队列容量、线程名前缀、拒绝策略及优雅关闭,并通过 @EnableAsync 启用,@Async 注解方法需为 public 且跨 Bean 调用,支持 void 或 Future 返回值,异常需内部捕获或 Future.get() 处理。

Spring 的 @Async 注解底层依赖线程池执行异步任务,默认使用 SimpleAsyncTaskExecutor(不复用线程),实际项目中必须自定义线程池才能合理控制并发、避免资源耗尽。
配置自定义线程池 Bean
Spring 会自动查找类型为 TaskExecutor 的 Bean 作为 @Async 的执行器。推荐定义一个 ThreadPoolTaskExecutor:
- 设置核心线程数(
corePoolSize)、最大线程数(maxPoolSize)、队列容量(queueCapacity)等关键参数 - 指定线程名称前缀(
threadNamePrefix),便于日志追踪 - 配置拒绝策略(如
CallerRunsPolicy),防止任务丢失 - 启用等待优雅关闭(
waitForTasksToCompleteOnShutdown = true)
示例配置:
@Bean("taskExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(8);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
启用 @Async 并指定线程池
在启动类或配置类上添加 @EnableAsync 开启异步支持。方法上加 @Async 即可异步执行:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 若项目中只有一个
TaskExecutorBean,@Async会自动使用它 - 若有多个线程池 Bean,需用
@Async("taskExecutor")显式指定 Bean 名称 - 被标注的方法必须是 public,且不能是同一个类内的调用(受限于 AOP 代理机制)
返回值与异常处理
@Async 方法支持返回 void 或 Future<T>(包括 CompletableFuture<T>):
- 返回
Future可以主动获取结果、判断完成状态、设置超时 - 异步方法内抛出的异常不会被调用方直接捕获,需在方法内 try-catch,或通过
Future.get()拿到并处理 - Spring 不会自动传播未捕获异常,建议配合
@Async方法内部记录日志或统一异常包装
注意事项与常见问题
实际使用中容易忽略的关键点:
- 确保目标方法由 Spring 容器管理(即该 Bean 是通过
@Service等注入的,不是 new 出来的) - 同一类中方法互相调用不生效:A 调 B,B 加了
@Async,但因代理失效,仍同步执行;应拆到不同 Bean 或通过ApplicationContext获取代理对象调用 - 事务方法 +
@Async:异步方法运行在新线程,不继承原事务上下文,需单独开启事务(@Transactional) - 线程池监控:可通过
ThreadPoolTaskExecutor的getThreadPoolExecutor()获取原生ThreadPoolExecutor,暴露指标供 Prometheus 或日志采集

















