I/O密集型业务,线程数要设置成CPU的两倍!不知道这是哪本书的作弊理论,但现在总有一些年轻人老拿这个定理来教书。他这话是骂人的话,毫无疑问,就好像他是权威的化身一样。以这样的理论为前提去讨论,真的很伤人。不幸的是,这样的理论站不住脚。只需要一个简单的反问,就会弄巧成拙:Tomcat默认的线程数是多少?它既不是2xCPU,也不是其他任何东西。在一些高并发的业务中,核心线程数可能达到几千甚至几万。对于一个Tomcat来说,它处理的大部分业务都是I/O密集型的,可以说是最佳实践场景。要理解设置线程数的奥秘,就必须了解I/O请求的特点。I/O请求不仅指磁盘读写,还指互联网服务中的网络I/O请求。I/O请求的速度远低于CPU运行的速度。大多数I/O请求在发起后进入等待状态。这种等待状态不会浪费CPU,所以一台机器可以同时支持很多I/O请求。如果I/O请求的速度很快,并且与CPU的耗时相当,那么我们将处理I/O的线程数设置为CPU的两倍是合理的。但实际上,没有那么多如果。我们每秒要处理数千个I/O请求,这注定比CPU占用的时间要多得多。像RPC组件,比如Dubbo服务器,也会设置比较大的线程数(比如600);Feign就不用多说了,短连接意味着更多线程的支持。这些是一些最佳实践。虽然I/O线程数增加了,但是会造成非常频繁的上下文切换,影响效率。但在互联网应用中,它是一个极好的解决方案。还有一个更好的解决方案,就是使用协程。协程是用户态的线程,是对普通线程进行更细粒度的划分。它运行在用户态,由用户调度,因此避免了频繁的上下文切换问题。但是协程在Java中并不成熟,它仍然是Golang语言的一个吸引人的特性。使用Golang开发的Web服务可以使用更少的线程来支持大量的I/O密集型请求。综上所述,题中的说法是不正确的,而且错的离谱。作者简介:品味小姐姐(xjjdog),一个不允许程序员走弯路的公众号。专注于基础架构和Linux。十年架构,每天百亿流量,与你探讨高并发世界,给你不一样的滋味。
