newFixedThreadPool不能真正限制并发数,因其使用无界队列LinkedBlockingQueue,任务持续堆积导致内存溢出和延迟失控;需手动构造ThreadPoolExecutor,配以有界队列和拒绝策略(如AbortPolicy)才能实现有效限流。

newFixedThreadPool 为什么不能真正限制并发数?
它确实会创建固定数量的线程,但 Executors.newFixedThreadPool 返回的 ThreadPoolExecutor 使用的是无界队列 LinkedBlockingQueue(默认容量 Integer.MAX_VALUE)。这意味着:只要任务提交速度 > 线程处理速度,新任务不会被拒绝,而是持续堆积在队列中——实际并发数始终是线程池大小,但**内存可能被撑爆,响应延迟不可控**。
怎么让超出容量的任务立刻失败或丢弃?
必须绕过 Executors 工厂方法,手写 ThreadPoolExecutor 构造,重点替换队列 + 拒绝策略:
- 用有界队列,比如
new ArrayBlockingQueue<runnable>(100)</runnable>,明确上限 - 拒绝策略选
ThreadPoolExecutor.AbortPolicy(抛RejectedExecutionException)或ThreadPoolExecutor.DiscardPolicy(静默丢弃) - 核心参数示例:
new ThreadPoolExecutor( 5, // corePoolSize 5, // maximumPoolSize 0L, // keepAliveTime TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(100), new ThreadPoolExecutor.AbortPolicy() );
submit() 和 execute() 的行为差异影响并发控制吗?
有。两者都走同一套队列+拒绝逻辑,但错误处理方式不同:
-
execute():直接运行,拒绝时抛RejectedExecutionException,需try/catch -
submit():包装成Future,拒绝时同样抛异常,但容易被忽略——尤其用invokeAll()或未检查Future.get()异常时 - 若用
submit()后不显式处理异常,看起来“任务没提交成功”却无提示,误以为并发控制失效
Spring 中 @Async 默认线程池为什么不遵守你设的 maxPoolSize?
因为 Spring Boot 2.1+ 默认用 TaskExecutionAutoConfiguration 创建线程池,其底层仍是 Executors.newFixedThreadPool 变体,且队列仍为无界。必须显式配置:
- 重写
TaskExecutorBean,用带界队列的手动构造实例 - 配置项如
spring.task.execution.pool.queue-capacity=100仅对 Spring 自动配置生效,且需配合max-size和拒绝策略(Spring 5.3+ 才支持配置拒绝策略) - 否则即使设了
max-size=5,队列仍无限,照样 OOM
newFixedThreadPool 就只是个假把式。

















