关于Spring Boot默认SimpleAsyncTaskExecutor仅启动8个线程的疑问
你提到的SimpleAsyncTaskExecutor文档确实说明它默认无并发线程数限制,但这里有个关键误区:Spring Boot在未显式定义Executor Bean时,@Async默认使用的并不是SimpleAsyncTaskExecutor,而是自动配置的ThreadPoolTaskExecutor实例。
为什么你看到只有8个任务同时运行?
Spring Boot自动配置的ThreadPoolTaskExecutor默认遵循以下规则:
- 核心线程数等于你的CPU核心数(你的机器是8核,所以核心线程数为8)
- 最大线程数为
Integer.MAX_VALUE - 使用无界的
LinkedBlockingQueue存储待执行任务
当你提交50个任务时,前8个会立即占用核心线程启动执行;剩余的42个任务会被放入无界队列,不会立即创建新线程,只有当核心线程空闲(即某个任务执行完成)后,才会从队列中取出下一个任务执行。这就是你看到的“必须等前8个完成才会执行剩余任务”的原因。
如何验证SimpleAsyncTaskExecutor的无限制行为?
如果你想真正使用SimpleAsyncTaskExecutor来验证它的无并发限制特性,只需要显式定义一个该类型的Bean即可,这样@Async就会优先使用这个Executor:
@Configuration @EnableAsync public class AsyncConfig { @Bean public Executor simpleAsyncTaskExecutor() { return new SimpleAsyncTaskExecutor(); } }
此时再运行你的代码,你会看到50个任务几乎同时打印STARTING...日志(只要操作系统允许创建足够多的线程)——虽然这会导致CPU被占满,但确实符合SimpleAsyncTaskExecutor“无并发限制”的定义。
补充说明
Spring Framework的文档中提到的@Async默认使用SimpleAsyncTaskExecutor是针对纯Spring Framework环境的,而Spring Boot基于自动配置,替换了这个默认实现,改用更适合生产环境的ThreadPoolTaskExecutor,这是你产生误解的核心原因。
内容的提问来源于stack exchange,提问作者IceMan

