ToB企服应用市场:ToB评测及商务社交产业平台

标题: Tomcat线程池详解,为什么SpringBoot最大支持200并发? [打印本页]

作者: 莫张周刘王    时间: 2024-10-22 08:00
标题: Tomcat线程池详解,为什么SpringBoot最大支持200并发?
Q:经典面试题,SpringBoot 应用可以同时并发处置惩罚多少请求?
A:SpringBoot 应用并发处置惩罚请求数主要由两个因素影响,使用的 Servlet容器(默认使用 Tomcat,常用的还有 jetty、undertow) 和 设置项。所以在默认设置下,SprigBoot 应用可以并发处置惩罚 200 请求。
那么这个200是怎么来的呢?SprigBoot 默认使用Tomcat,而Tomcat线程池的最大线程数就是200。到这里有朋友就有疑问了,并发数不是应该先受队列长度影响吗,难道队列长度也只有200,才会使用最大线程数吗?
Tomcat线程池

JDK 的线程池,是先使用核心线程数设置,接着使用队列长度,最后再使用最大线程设置。
Tomcat 的线程池,就是先使用核心线程数设置,再使用最大线程设置,最后才使用队列长度。
底层源码

runWorker

进入 runWorker 之后,这部分代码看起来很眼熟:

在 getTask 方法内里,可以看到关于线程池的几个关键参数:

而且基于 maximumPoolSize 这个参数,往前翻代码,会发现这个默认值就是 200:

Tomcat线程池默认队列长度:

Tomcat线程池:
往线程池内里提交任务的时候,会实行 execute 这个方法:

对于 Tomcat 它会调用到 executeInternal 这个方法:

这个方法内里,标号为
接下来看 workQueue.offer(command) 这个逻辑。如果返回 true 则表示加入到队列,返回 false 则表示启用最大线程数嘛。
workQueue.offer

这个 workQueue 是 TaskQueue,是 Tomcat 自己基于 LinkedBlockingQueue 搞的一个队列。

标号为 ① 的地方,判断了 parent 是否为 null,如果是则直接调用父类的 offer 方法。说明要启用这个逻辑,我们的 parent 不能为 null。

parent 就是 Tomcat 线程池,通过其 set 方法可以知道,是在线程池完成初始化之后,进行了赋值。也就是说,在 Tomcat 的场景下,parent 不会为空。
标号为 ② 的地方,调用了 getPoolSizeNoLock 方法:这个方法是获取当前线程池中有多个线程。所以如果这个表达式为 true:

parent.getPoolSizeNoLock() == parent.getMaximumPoolSize()
就表明当前线程池的线程数已经是设置的最大线程数了,那就调用 offer 方法,把当前请求放到到队列内里去。
标号为 ③ 的地方,是判断已经提交到线程池内里待实行或者正在实行的任务个数,是否比当前线程池的线程数还少。如果是,则说明当前线程池有空闲线程可以实行任务,则把任务放到队列内里去,就会被空闲线程给取走实行。
标号为 ④ 的地方。如果当前线程池的线程数比线程池设置的最大线程数还少,则返回 false。offer 方法返回 false,会出现什么情况?

offer返回false 则开始到上图中标号为 ③ 的地方,去尝试添加非核心线程了,也就是启用最大线程数这个设置了。
总结

JDK 的线程池,是先使用核心线程数设置,接着使用队列长度,最后再使用最大线程设置。
Tomcat 的线程池,就是先使用核心线程数设置,再使用最大线程设置,最后才使用队列长度。
那么如何调解增大SpringBoot的最大线程数呢?看到这里应该已经明确了,可以通过调解 最大线程数来 控制并发数目
面试题专栏

Java面试题专栏已上线,欢迎访问。
那么可以私信我,我会尽我所能资助你。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4