从“先入队”到“先扩容”:为什么 Tomcat 要魔改 JDK 原生线程池的执行顺序

2 阅读5分钟

今天咱们不聊那些深入的话题,来聊一个很多兄弟在面试或者实际调优时都会懵圈的问题:

为什么 Java 原生线程池(ThreadPoolExecutor)是“核心线程满 -> 排队 -> 队列满 -> 才创建最大线程”?

而 Tomcat 的线程池却是“核心线程满 -> 直接创建最大线程 -> 队列满 -> 才拒绝”?

这俩是不是搞反了?到底谁才是对的?别急,咱们搬个小板凳,用大白话把这事儿捋清楚。

Java 原生线程池:先排队,后加人

首先,咱们看看 JDK 自带的 ThreadPoolExecutor 的逻辑。它的执行流程大概是这样的:

  1. 来个任务,核心线程数(corePoolSize)没满?直接新建线程干活
  2. 核心线程满了?别急着加人,先去队列(workQueue)里排着
  3. 队列也满了?这时候才考虑创建非核心线程,直到达到最大线程数(maximumPoolSize)
  4. 最大线程数也满了?那就对不起了,触发拒绝策略

很多初学者的第一反应是: “这不合理啊!队列都堆积如山了,说明忙不过来了,为什么不赶紧多招人(创建新线程)来帮忙,反而让任务在那干等着?”

其实,JDK 的设计者这么定,核心逻辑就两个字:资源

保护系统,防止“虚胖”

想象一下,你是一个包工头(CPU)。核心线程是你手下的正式员工,能力强,长期雇佣。最大线程是你临时去劳务市场找的兼职,成本高,管理麻烦。队列是门口的等候区。

如果按照“先加人”的逻辑:只要正式员工忙不过来,你就疯狂招兼职。万一只是瞬间来了一个小高峰(比如突发流量),你招了一堆兼职,结果人家刚到位,流量没了。这一堆兼职线程空转,不仅浪费 CPU 上下文切换的资源,还占内存。

JDK 的逻辑是: 正式员工忙了,让任务在门口(队列)等一会儿。如果只是瞬间高峰,等几秒钟,正式员工手头活干完了,立马就能把门口的活接了,根本不需要招兼职。

只有当门口(队列)真的堵死了,说明这波流量不是暂时的,是持续的洪峰,这时候再招兼职(最大线程)也不迟。

2. 适用场景:IO 密集型 vs 计算密集型

JDK 这种设计,特别适合任务执行时间较短、且希望控制资源消耗的场景。它倾向于用“空间(队列内存)换时间(线程创建开销)”,优先保证系统的稳定性,避免线程数爆炸。

Tomcat 线程池:先加人,后排队

好了,再看 Tomcat。如果你去翻 Tomcat 的源码或者配置,你会发现它的逻辑完全是反过来的:

  1. 来个请求,核心线程没满?新建线程
  2. 核心线程满了?别排队!直接创建新线程,直到达到最大线程数
  3. 最大线程数也满了?这时候才让请求去队列(AcceptCount)里排队
  4. 队列也满了?拒绝连接

这就奇怪了,Tomcat 为啥跟 JDK 对着干?

Web 服务器的特殊性:快速响应

Tomcat 是干嘛的?它是处理 HTTP 请求的。Web 请求有一个特点:用户是在线等待的

如果用 JDK 那套逻辑:

  • 用户发起请求。
  • 核心线程满了。
  • 用户被扔进队列排队。
  • 注意: 在 Java 原生线程池里,如果队列是无界的(比如 LinkedBlockingQueue),或者队列很大,任务可能会在队列里躺很久,直到核心线程空闲。
  • 对于用户来说,这就是接口超时、页面转圈圈、甚至直接报错

Tomcat 的逻辑是:能多开一个线程处理,就绝不让用户排队!

2. 避免“队头阻塞”效应

在 Web 场景下,如果大量请求进入队列,而处理速度跟不上,队列会迅速变长。

  • JDK 模式风险:请求在队列里积压,响应时间不可控。哪怕后面有闲置的“最大线程”名额,但因为队列没满,这些名额根本不会启动。这就造成了资源闲置(有名额不用)和用户体验差(用户在排队)并存的尴尬局面。
  • Tomcat 模式优势:只要还没达到最大线程上限,立刻新开线程处理请求。这样能最大程度利用服务器资源,降低平均响应时间(RT) 。只有当服务器真的扛不住了(线程数达到最大值),才让后续请求排队(此时通常意味着系统已经过载,排队也是一种保护)。

3. 这里的“队列”含义不同

还要区分一下概念:

  • JDK 线程池的队列:存的是 Runnable 任务对象,是在内存里的。
  • Tomcat 的队列(AcceptCount) :在达到最大线程数后,新的 TCP 连接会在操作系统内核的监听队列里排队,或者在 Tomcat 的应用层队列等待。这时候客户端通常会表现为“连接建立中”或者超时。Tomcat 宁愿先耗尽线程资源,也不愿过早让连接进入应用层排队,因为线程是可以并发处理的,而队列是串行的等待

说到这,大家应该明白了。这俩都不是“反着来”,而是针对不同的业务场景做的最优解

更多内容请关注我的公众号

简迅云笔记

推荐一个 ai 工具网站 码盒工具