核心线程数(固定不销毁)、最大线程数(阻塞队列满了之后创建临时救场的线程,用完就销毁|最大线程数=核心线程数+临时线程数)、阻塞队列(暂时存储任务,决定线程池吞吐能力)、拒绝策略(阻塞队列满了而且最大线程数也到了,对后续的任务所采用的策略)
java.util.concurrent.ThreadPoolExecutor中,线程池的运作由 7 个核心参数严格控制
7个核心参数
1. corePoolSize (核心线程数)
- 定义:线程池中常驻的“正式工”数量。
- 逻辑:即便这些线程处于空闲状态,也不会被销毁(除非显式开启了
allowCoreThreadTimeOut)。当新任务提交时,只要当前运行的线程数小于设定值,就会直接创建新线程来执行任务。
2. maximumPoolSize (最大线程数)
- 定义:线程池能够容纳的最大并发线程极限(核心线程 + 非核心线程)。
- 逻辑:只有当阻塞队列(
workQueue)被塞满时,线程池才会开始创建超出corePoolSize的“临时工”线程来救场,直到总数达到maximumPoolSize。
3. keepAliveTime & unit (空闲存活时间及单位)
- 定义:非核心线程空闲等待新任务的最长时间。
- 逻辑:当线程池中的线程数量超过
corePoolSize时,如果这些多出来的“临时工”线程闲置时间超过了该设定值,就会被内核回收,以释放系统资源。
4. workQueue (工作队列 / 阻塞队列)
- 定义:用于缓冲等待执行任务的并发安全队列。这是决定线程池吞吐能力与内存安全的关键。
- 工程陷阱:在开发承受高并发流量的底层服务(如服务端 RPC 节点接收密集请求)时,绝对禁止使用无界队列(如默认容量为
Integer.MAX_VALUE的LinkedBlockingQueue)。一旦遇到突发流量或下游处理变慢,无限堆积的任务会迅速耗尽 JVM 堆内存,直接引发 OOM。必须使用有界队列(如ArrayBlockingQueue)进行硬性物理拦截。
5. threadFactory (线程工厂)
- 定义:用于定制线程创建逻辑的工厂接口。
- 工程规范:严禁使用默认工厂(产出如
pool-1-thread-1这样毫无语义的名称)。必须通过自定义工厂为线程赋予具有业务含义的名称(例如rpc-provider-worker-%d)。如果不强制命名,当在 Linux 环境下通过top -H定位 CPU 飙升的底层线程,或通过jstack抓取堆栈快照排查死锁时,根本无法分辨异常线程属于哪个业务模块。
6. handler (拒绝策略)
- 定义:当线程数达到
maximumPoolSize且workQueue也已满时,针对继续涌入的新任务所采取的阻断机制。 - 默认策略:
AbortPolicy(默认):直接抛出RejectedExecutionException异常。CallerRunsPolicy:将任务退回给调用者,由提交任务的当前线程(如 Netty 的 IO 线程)直接执行。注意:这会阻塞调用方的上游线程,可能导致网络吞吐量断崖式下跌。DiscardPolicy:静默丢弃任务,不抛出异常。DiscardOldestPolicy:丢弃队列头部滞留最久的老任务,将新任务强行塞入。
- 定制化:在严谨的系统设计中,通常需要实现自定义拒绝策略,例如将溢出的请求参数持久化到日志或消息队列中,或者向客户端返回特定的限流/降级响应报文。
线程池复用原理(Worker任务循环)
java.util.concurrent.ThreadPoolExecutor中,线程池的运作由 7 个核心参数严格控制
7个核心参数
1. corePoolSize (核心线程数)
- 定义:线程池中常驻的“正式工”数量。
- 逻辑:即便这些线程处于空闲状态,也不会被销毁(除非显式开启了
allowCoreThreadTimeOut)。当新任务提交时,只要当前运行的线程数小于设定值,就会直接创建新线程来执行任务。
2. maximumPoolSize (最大线程数)
- 定义:线程池能够容纳的最大并发线程极限(核心线程 + 非核心线程)。
- 逻辑:只有当阻塞队列(
workQueue)被塞满时,线程池才会开始创建超出corePoolSize的“临时工”线程来救场,直到总数达到maximumPoolSize。
3. keepAliveTime & unit (空闲存活时间及单位)
- 定义:非核心线程空闲等待新任务的最长时间。
- 逻辑:当线程池中的线程数量超过
corePoolSize时,如果这些多出来的“临时工”线程闲置时间超过了该设定值,就会被内核回收,以释放系统资源。
4. workQueue (工作队列 / 阻塞队列)
- 定义:用于缓冲等待执行任务的并发安全队列。这是决定线程池吞吐能力与内存安全的关键。
- 工程陷阱:在开发承受高并发流量的底层服务(如服务端 RPC 节点接收密集请求)时,绝对禁止使用无界队列(如默认容量为
Integer.MAX_VALUE的LinkedBlockingQueue)。一旦遇到突发流量或下游处理变慢,无限堆积的任务会迅速耗尽 JVM 堆内存,直接引发 OOM。必须使用有界队列(如ArrayBlockingQueue)进行硬性物理拦截。
5. threadFactory (线程工厂)
- 定义:用于定制线程创建逻辑的工厂接口。
- 工程规范:严禁使用默认工厂(产出如
pool-1-thread-1这样毫无语义的名称)。必须通过自定义工厂为线程赋予具有业务含义的名称(例如rpc-provider-worker-%d)。如果不强制命名,当在 Linux 环境下通过top -H定位 CPU 飙升的底层线程,或通过jstack抓取堆栈快照排查死锁时,根本无法分辨异常线程属于哪个业务模块。
6. handler (拒绝策略)
- 定义:当线程数达到
maximumPoolSize且workQueue也已满时,针对继续涌入的新任务所采取的阻断机制。 - 默认策略:
AbortPolicy(默认):直接抛出RejectedExecutionException异常。CallerRunsPolicy:将任务退回给调用者,由提交任务的当前线程(如 Netty 的 IO 线程)直接执行。注意:这会阻塞调用方的上游线程,可能导致网络吞吐量断崖式下跌。DiscardPolicy:静默丢弃任务,不抛出异常。DiscardOldestPolicy:丢弃队列头部滞留最久的老任务,将新任务强行塞入。
- 定制化:在严谨的系统设计中,通常需要实现自定义拒绝策略,例如将溢出的请求参数持久化到日志或消息队列中,或者向客户端返回特定的限流/降级响应报文。
线程池复用原理(Worker任务循环)

| 情况 | 说明 |
|---|---|
| 核心线程 + 队列空 | 默认调 take(),永久阻塞等待,不退出 |
| 非核心线程 + 队列空 | 调 poll(keepAliveTime),超时还没任务就返回 null → 线程退出 |
allowCoreThreadTimeOut = true | 核心线程也会超时退出 |
线程池被 shutdown() | 中断空闲线程,getTask() 返回 null |
task.run()而不是task.start()——直接在当前 Worker 线程里执行任务的run方法,不会创建新线程getTask()从阻塞队列取任务。队列空了线程就阻塞等待(take()),不是销毁- 整个 Worker 线程的生命周期就是这个
while循环,循环不结束,线程就一直活着

5912

被折叠的 条评论
为什么被折叠?



