Spring中@Async实现异步调用需三步:启用@EnableAsync、配置ThreadPoolTaskExecutor线程池(避免默认SimpleAsyncTaskExecutor资源耗尽)、方法满足public且跨类调用;异常需通过Future.get()或CompletableFuture.exceptionally()捕获。

Spring 使用 @Async 注解实现异步调用,核心在于开启异步支持、配置线程池,并确保方法调用满足代理条件。不配置自定义线程池时会使用默认的 SimpleAsyncTaskExecutor(非复用线程),实际项目中必须手动配置线程池以避免资源耗尽。
启用 @Async 支持
在 Spring Boot 主启动类或任意配置类上添加 @EnableAsync 注解,这是启用异步功能的前提:
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
定义线程池 Bean
推荐通过 @Configuration 类声明一个 ThreadPoolTaskExecutor Bean,并设置核心参数。该 Bean 名称默认为 taskExecutor,@Async 会自动匹配;也可显式指定名称:
- 设置
corePoolSize和maxPoolSize控制线程数量 - 设置
queueCapacity避免无界队列导致内存溢出 - 设置
threadNamePrefix便于日志追踪 - 启用
waitForTasksToCompleteOnShutdown保证优雅关闭
示例配置:
@Configuration
public class AsyncConfig {
@Bean("taskExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(8);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-");
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
}
在方法上使用 @Async
被 @Async 标记的方法必须满足以下条件才能真正异步执行:
- 方法必须是 public 的(private 或 package-private 不生效)
- 不能是同一个类内的 self-invocation(即本类内部直接调用,因代理失效)
- 返回类型建议为
void或Future>(如CompletableFuture) - 若需指定线程池,可用
@Async("taskExecutor")显式引用 Bean 名
正确示例:
@Service
public class EmailService {
@Async("taskExecutor") // 指定线程池
public CompletableFuture<void> sendEmailAsync(String to, String content) {
// 模拟发送邮件耗时操作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Email sent to " + to);
return CompletableFuture.completedFuture(null);
}
}</void>
调用方需通过依赖注入获取该 Service 实例并调用,不能 new 对象或本类内调用。
处理异常与返回结果
@Async 方法抛出的异常不会传播到调用方线程,默认会被吞掉。如需捕获异常:
- 返回
Future类型,调用future.get()时会重新抛出原始异常 - 使用
CompletableFuture链式处理:`.exceptionally()` 或 `.handle()` - 全局配置
AsyncUncaughtExceptionHandler捕获未处理异常
例如:
emailService.sendEmailAsync("user@example.com", "Hello")
.exceptionally(ex -> {
log.error("Failed to send email", ex);
return null;
});
不复杂但容易忽略细节,关键在配置线程池、保证代理生效、合理处理返回和异常。











