请教下关于 Tomcat 线程池和 Java 中 ExecutorService 线程池的问题

343 天前
 VB1

咨询下各位大佬,为什么 tomcat 的默认的最大的线程数是 200 ,但是在项目里面( IO 密集型)设置的最大线程数是 2 * CPU 核心数?

1253 次点击
所在节点    Java
10 条回复
themostlazyman
343 天前
Tomcat 多个线程为了提高并发(IO 密集); 2 * CPU 核心数一般是处理器支持一个核虚拟两个核的 CPU 的设置(计算密集或者多进程应用)。
huang119412
343 天前
IO 密集型线程数设为 2 * CPU ,此时的 IO 是 NIO , 如果是 OIO 则线程数是 2 * CPU 不合理,Tomcat 一般需要配合关系型数据库使用,Web 项目的瓶颈都是在数据库,而 JDBC (关系型数据库)并不支持异步,异步也没什么意义,所以 Tomcat 的线程数设置的看起来非常多。但是线程的切换时间和 IO 的阻塞时间比基本上可以忽略不记。
VB1
343 天前
@themostlazyman
@huang119412
感谢二位的回答,但是一个 springboot 里面,内置 tomcat ,在一台机器上(假设 CPU8 核)启动 springboot 项目后,所有的线程共享这台机器的 CPU ,但是为啥 tomcat 的线程数(最大 200)和项目中线程池的线程数(最大 16)相差如此之大。也就是说为什么 tomcat 可以不受这个 2 * CPU 核心数这个限制?
Goooooos
343 天前
每个请求到在线程池的一个线程处理,大部分请求都由于外部 IO 请求而阻塞,导致该请求所在的线程阻塞
如果同一秒内所有请求都阻塞在 IO 上(如查询 Mysql ),那么此时 CPU 就变得空闲了
加大线程池最大线程数量,可以在同 1 秒内处理更多请求,更好利用 CPU
但线程数量也不能无限大,频繁的上下文切换也是很消耗 CPU 的
升级 JDK21 后可以尝试虚拟线程,这种场景能更好的提高 CPU 利用率
yty2012g
343 天前
后面的设置不太合理,如果是 IO 密集型,很容易出现线程池内线程不够用的情况
anonydmer
343 天前
楼主混淆了两个概念,servlet 容器的线程池和应用业务的线程池。tomcat 配置的 200 个线程是用来处理 servlet 请求的,就是说,有请求到来时候,tomcat 总共用多少个线程来处理请求的业务逻辑操作(不是请求本身的 io ),这个逻辑操作对应的就是你 spring mvc 中某个 controller 的一个 action 方法。 在这些业务逻辑操作中,如果你还需要做多线程操作,就需要你自己管理一个线程池,就是你说的后面这个线程池,因为在业务中一般都是做 io 操作,io 操作不需要很多的线程数量就够了。
anonydmer
343 天前
在这种模式下,tomcat 的并发性能其实是受到最大线程数量限制的。太多的线程会对 CPU 造成频繁的上下文切换。 如果系统是 IO 密集型的,针对这个问题先前一种可行的方式是用事件驱动的框架,例如 Spring WebFlux; 但是现在 Java 21 已经支持了虚拟线程,我们可以在不改变编程模型的基础上达到和 SpringWebFlux 类型的性能,目前 SpringBoot 已经支持虚拟现场了,楼主可以测试一下让 tomcat 用虚拟线程,在 IO 场景下,性能会好很多。
wysnxzm
343 天前
virtual thread 对这类问题是降维打击
JYii
343 天前
@wysnxzm #8 是的,springboot3.2.0 支持配置 spring.threads.virtual.enabled=true ,以后再也不用配置什么线程池了
VB1
343 天前
@anonydmer 明白了,感谢解惑。业务逻辑操作中确实很少有需要另外再做多线程操作的,再加上 io 密集型的原因,也就不需要很多的线程数量。2 * CPU 的核心数能涵盖很多场景。


@wysnxzm
@JYii
这就去学习虚拟线程,感谢回复。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/998663

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX