问:
如果同时发出了100个异步请求,超过了能处理的最大线程,线程池的工作机制是怎么样的呢?
线程池大小:
XML
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="queueCapacity" value="50" />
<property name="keepAliveSeconds" value="60" />
<property name="threadNamePrefix" value="ssh-thread-" />
<property name="rejectedExecutionHandler">
<bean
class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
</property>
</bean>
<task:annotation-driven executor="taskExecutor"/>
-
核心线程处理
前5个请求会立即由核心线程(corePoolSize=5)执行,此时活跃线程数达到核心线程数上限。
-
队列缓冲
接下来的50个请求(queueCapacity=50)会被放入工作队列等待执行,此时队列满负荷。
-
扩展线程处理
当队列满后,线程池会创建新线程处理后续请求,直到线程总数达到maxPoolSize=10。此时会再处理5个请求(10-5=5),总处理量为:5(核心) + 5(扩展) = 10个并发执行任务。
-
拒绝策略触发(注1)
剩余40个请求(100-5-50-5)将触发CallerRunsPolicy策略,由提交任务的调用线程(如HTTP请求的Tomcat线程)同步执行这些任务,导致调用方阻塞。
关键指标总结
- 并发执行线程数:10(maxPoolSize)
- 队列堆积任务数:50(queueCapacity)
- 同步降级任务数:40(CallerRunsPolicy处理)
- 线程空闲回收:非核心线程60秒(keepAliveSeconds)后自动销毁。
注1:什么是拒绝策略

通俗解释线程池的CallerRunsPolicy
策略
当线程池(比如你配置的5核心线程+10最大线程+50队列)被100个任务同时塞满时,会发生以下情况:
- 前5个任务:直接由5个核心线程处理(像5个固定工人开工)。
- 接下来的50个任务:排队等待(像把任务扔进一个能装50个任务的篮子)。
- 再接下来的5个任务:临时再招5个工人(总工人数达到10个上限)。
- 最后40个任务 :
- 因为工人和篮子都满了,线程池会喊:"**谁提交的任务谁自己干!**"
- 比如Tomcat线程(处理HTTP请求的线程)会被迫停下当前工作,直接去执行这40个任务,导致网页响应变慢甚至卡死。
类比 :
想象餐厅只有10个厨师(线程),50个待做菜的订单(队列)。突然来了100个订单:
-
前10个厨师先做10个菜(5个固定厨师+5个临时工)。
-
50个订单排队等。
-
剩下的40个订单?老板(调用线程)只能亲自下厨,结果顾客(用户)等更久了。
关键点:
- 这种策略能保证任务不丢失,但会拖慢提交任务的线程(比如网页响应变慢)。
- 适合对任务完整性要求高,但能接受短暂延迟的场景