写点什么

为什么说 IO 密集型业务,线程数是 CPU 数的 2 倍?

作者:小小怪下士
  • 2023-01-04
    湖南
  • 本文字数:758 字

    阅读完需:约 2 分钟

I/O 密集型业务,线程数量要设置成 CPU 的 2 倍!


也不知道这是哪本书的坑爹理论,现在总有一些小青年老拿着这样的定理来说教。说的信誓旦旦,毋庸置疑,仿佛是权威的化身。讨论时把这样的理论当作前提,​真的是受害不浅。


但可惜的是,这样的理论站不住脚。我只需要一个简单的反问,它就不攻自破:


Tomcat 的默认线程数是多少呢?


它既不是 CPU 的 2 倍,也不是什么其他数值。在某些高并发的服务中,它的核心线程数,可能达到数千甚至上万。对于一个 Tomcat 来说,它处理的大多数都是 I/O 密集型的业务,可以说是最好的实践场景。


要明白这个线程数设置的玄机,就必须了解 I/O 请求的特点。I/O 请求不仅仅指的是磁盘读写,在互联网服务中更多指的是网络 I/O 请求。


I/O 请求的速度,要远低于 CPU 运行的速度。大部分 I/O 请求,在发起之后,就进入等待状态,这个等待状态不会浪费 CPU,所以一台机器在同一时刻支持的 I/O 请求,可以很多。


如果 I/O 请求的速度比较快,和 CPU 的耗时对等的时候,我们把处理 I/O 的线程数,设置成 CPU 的 2 倍,是合理的。但现实中并没有这么多如果,我们要处理秒成千上万的 I/O 请求,注定了它的耗时要比 CPU 多的多。


像 RPC 组件,比如 Dubbo 服务端,也会设置一个比较大的线程数(比如 600);Feign 这种就更不用多说了,短连接意味着更多线程数的支持。这都是些最佳实践。


虽然 I/O 线程数量增多,会造成非常频繁的上下文切换,进而影响效率。但在互联网应用中,它却是一个优秀的解决方案。


更优秀的解决方式也有,那就是使用协程。协程是用户态的线程,是对普通线程更细粒度的划分。它是在用户态运行的,由用户自行调度,所以也就避免了频繁的上下文切换问题。


但协程在 Java 中还不成熟,它依然是 Golang 语言的诱人特性。使用 Golang 开发的 Web 服务,可以采用更少的线程来支持大量 I/O 密集型的请求。


综上所述,标题的表述并不正确,而且错的离谱。

用户头像

还未添加个人签名 2022-09-04 加入

热衷于分享java技术,一起交流学习,探讨技术。 需要Java相关资料的可以+v:xiaoyanya_1

评论

发布
暂无评论
为什么说IO密集型业务,线程数是CPU数的2倍?_Java_小小怪下士_InfoQ写作社区