Spring Boot异步任务需用@EnableAsync开启支持并自定义线程池,@Async方法应返回CompletableFuture,避免默认线程池导致OOM;调用须经Spring代理且不可与@Transactional同方法使用。

Spring Boot 实现异步任务,核心是 @Async 注解配合自定义线程池——不配线程池的 @Async 在生产环境极易出问题,比如线程泄漏、任务堆积、OOM 或响应延迟不可控。
必须开启异步支持
在启动类或配置类上加 @EnableAsync,这是整个机制的开关:
- 没有它,@Async 方法会退化为同步执行,日志里看不到新线程名,但代码看似“没报错”
- 推荐放在主启动类上,避免遗漏;若用独立配置类,需确保该类被 Spring 扫描到
定义带返回值的异步方法
优先返回 CompletableFuture<T>,比 void 或 Future 更灵活、可组合、支持链式调用:
- void 类型无法感知执行结果和异常,调试困难
- Future.get() 是阻塞的,容易误用导致主线程卡住
- CompletableFuture 可用 thenApply、exceptionally、allOf 等做编排,适合复杂异步流
示例:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
@Service<br>public class AsyncService {<br> @Async("myThreadPool")<br> public CompletableFuture<String> sendNotification(String userId) {<br> // 模拟发送短信或推送<br> try { Thread.sleep(800); } catch (InterruptedException e) {<br> Thread.currentThread().interrupt();<br> return CompletableFuture.failedFuture(e);<br> }<br> return CompletableFuture.completedFuture("sent to " + userId);<br> }<br>}
自定义线程池(关键!)
默认线程池 SimpleAsyncTaskExecutor 不复用线程,每次新建线程,高并发下直接打爆 JVM。必须显式配置线程池 Bean:
- 用 @Bean 声明线程池,并指定唯一 bean 名(如 "myThreadPool"),@Async 可通过名称精准绑定
- 核心参数要合理:core-size(5–10)、max-size(20–50)、queue-capacity(100–500),根据业务吞吐预估
- 设置 RejectedExecutionHandler,推荐 CallerRunsPolicy(主线程兜底执行)或 DiscardPolicy(丢弃非关键任务)
- 务必设 threadNamePrefix,方便日志追踪线程来源
配置示例(Java Config):
@Configuration<br>public class AsyncConfig {<br> @Bean("myThreadPool")<br> public Executor myThreadPool() {<br> ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();<br> executor.setCorePoolSize(8);<br> executor.setMaxPoolSize(32);<br> executor.setQueueCapacity(200);<br> executor.setThreadNamePrefix("async-notify-");<br> executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());<br> executor.initialize();<br> return executor;<br> }<br>}
注意调用方式与事务边界
@Async 生效有硬性前提,踩坑多集中在这两点:
- 必须是 Spring 管理的 Bean 内部调用:不能在同一个类里 this.xxx() 调用,必须通过接口注入后由代理触发
- @Async 方法不能与 @Transactional 同处一个方法内:异步线程不在原事务上下文中,数据库操作会丢失事务控制,需单独处理数据一致性
- 异常默认不会抛给调用方,建议在 CompletableFuture 中显式捕获并封装

















