配置 @Async 时,先确认 Spring Boot 版本和实际选中的执行器。线程池默认值属于具体版本的实现,不能把“8 个核心线程、最大线程数无限大”当成所有 Boot 项目的固定行为。
默认值为什么容易被误读
以下仅以 Spring Boot 2.7.18 的 TaskExecutionProperties 为例:
| 属性 | 该版本默认值 |
|---|---|
| pool.core-size | 8 |
| pool.max-size | Integer.MAX_VALUE |
| pool.queue-capacity | Integer.MAX_VALUE |
| pool.keep-alive | 60 秒 |
| pool.allow-core-thread-timeout | true |
| thread-name-prefix | task- |
无界队列下,任务通常先排队,max-size 不能按想象无限扩充线程。风险可能表现为积压和等待变长,不能仅凭默认最大值断言会立刻创建大量线程。2.7.18 属性源码
配置 Boot 自动提供的执行器
下面容量只是示例,需要按任务耗时、内存和下游并发能力调整:
spring:
task:
execution:
thread-name-prefix: business-
pool:
core-size: 4
max-size: 8
queue-capacity: 100
keep-alive: 60s
thread-name-prefix 位于 execution 下,与 pool 同级。这里没有通用的 spring.task.execution.enabled 开关;异步方法处理还需要 @EnableAsync,且自定义 Executor 等条件会影响 Boot 自动配置是否生效。
明确指定一个业务执行器
若项目有多个池,直接用名字绑定更清楚。以下是 Spring 5.x 的配置类:
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean("businessExecutor")
public Executor businessExecutor() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setCorePoolSize(4);
pool.setMaxPoolSize(8);
pool.setQueueCapacity(100);
pool.setThreadNamePrefix("business-");
pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
return pool;
}
}
将 @Async(“businessExecutor”) 标在 Spring 管理的服务方法上,通过注入的代理对象调用。由容器管理的 ThreadPoolTaskExecutor 会参与 Bean 生命周期;不要为了运行示例在每个请求里新建线程池。
@Async 默认依赖代理,同一个对象内部直接调用自身方法不会自动变成异步。void 方法异常与 Future/CompletableFuture 异常的观察方式也不同;任务提交被拒绝时还要明确业务如何反馈,不能把“调用立即返回”当作执行成功。Boot 任务执行说明
如何确认配置真的生效
先在开发环境确认调用线程与执行线程名称,再观察池大小、队列和拒绝次数。若名称仍不是预期值,检查 Bean 名称、@Async 指定值以及是否发生自调用。容量测试应同时观察下游承载能力,增加线程数并不必然增加吞吐。