V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
VB1
V2EX  ›  Java

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

  •  1
     
  •   VB1 · 2023-12-08 13:43:11 +08:00 · 1313 次点击
    这是一个创建于 386 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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


    @wysnxzm
    @JYii
    这就去学习虚拟线程,感谢回复。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2657 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 11:56 · PVG 19:56 · LAX 03:56 · JFK 06:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.