Tomcat线程池必须在server.xml中配置,环境变量无效;因线程池由Executor和Connector XML元素定义,仅JVM参数受JAVA_OPTS影响,系统属性和自定义环境变量不被Tomcat读取或解析。

Tomcat线程池不通过环境变量配置,所有关键参数必须写在 server.xml 里;试图用环境变量(如 JAVA_OPTS)覆盖 maxThreads 或 acceptCount 是无效的。
为什么不能用环境变量配线程池
Tomcat 的线程池由 Executor 和 Connector 元素共同定义,它们属于 XML 配置驱动的运行时组件,启动时由 Catalina 解析并构造 Java 对象。环境变量(如 JAVA_OPTS)只影响 JVM 启动参数(堆内存、GC 策略等),对 Tomcat 自身的连接器和线程池结构无任何作用。
常见误操作包括:
- 在
catalina.sh中设置JAVA_OPTS="-DmaxThreads=500"—— 这个系统属性不会被 Tomcat 读取,完全被忽略 - 尝试用
export TOMCAT_THREADS=300再期望 server.xml 里用${TOMCAT_THREADS}引用 —— Tomcat 默认不支持这种 EL 表达式解析,会直接报错或当作字符串字面量处理
正确配置位置:只改 server.xml
线程池配置必须显式写在 $CATALINA_HOME/conf/server.xml 中,分两步:
1. 定义共享线程池(<executor></executor>):
<Executor name="tomcatThreadPool"
namePrefix="tomcatThreadPool-"
maxThreads="800"
minSpareThreads="100"
maxIdleTime="60000"
prestartminSpareThreads="true"/>
2. 在 <connector></connector> 中引用它:
<Connector executor="tomcatThreadPool"
port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
acceptCount="200"
redirectPort="8443"/>
注意:prestartminSpareThreads="true" 很关键——它让 Tomcat 启动时就创建 minSpareThreads 个线程,避免首波请求触发线程创建延迟。
acceptCount 不是线程数,别和 maxThreads 混
这是最常被误解的点:acceptCount 是 TCP 连接层的等待队列长度(即 OS 的 backlog),不是应用层线程数。
当所有 maxThreads 线程都在忙,新 TCP 连接会进入这个队列;队列满后,OS 直接 RST 掉后续连接,客户端看到的是“Connection refused”,而不是 503。
所以实际并发承载能力 ≈ maxThreads + acceptCount,但二者角色完全不同:
-
maxThreads:决定能同时执行多少个 HTTP 请求(受 CPU、IO、业务逻辑阻塞影响) -
acceptCount:仅缓冲“刚连上还没分配到线程”的 TCP 连接,不消耗 JVM 堆,但过大会拖长连接建立延迟
Spring Boot 用户特别注意
如果你用的是 Spring Boot 内嵌 Tomcat(默认情况),server.xml 根本不存在——你要改的是 application.yml 或 application.properties:
server:
tomcat:
threads:
max: 800
min-spare: 100
accept-count: 200
max-connections: 10000
这些配置最终会被 TomcatServletWebServerFactory 转成对应的 Executor 和 Connector 实例。不要试图去手动建 server.xml,它会被忽略。
线程名仍为 http-nio-8080-exec-X,可通过 jstack <pid> 验证是否生效。

















