1000个并发线程,10台机器,每台机器4核,设计线程池大小 (2)

简介: 1000个并发线程,10台机器,每台机器4核,设计线程池大小 (2)

关于 JDK 线程池的 7 个参数和执行流程。


虽然我很久没有参加面试了,但是我觉得这题属于必考题吧。


所以如果你真的还不会,麻烦你写个 Demo ,换几个参数调试一下。把它给掌握了。


而且还得多注意由这些知识点引申出来的面试题。


比如从图片也可以看出来,JDK 线程池中如果核心线程数已经满了的话,那么后面再来的请求都是放到阻塞队列里面去,阻塞队列再满了,才会启用最大线程数。


但是你得知道,假如我们是 web 服务,请求是通过 Tomcat 进来的话,那么 Tomcat 线程池的执行流程可不是这样的。


Tomcat 里面的线程池的运行过程是:如果核心线程数用完了,接着用最大线程数,最后才提交任务到队列里面去的。这样是为了保证响应时间优先。


所以,Tomcat 的执行流程是这样的:


微信图片_20220426233339.png


其技术细节就是自己重写了队列的 offer 方法。在这篇文章里面说的很清楚了,大家可以看看:


《每天都在用,但你知道 Tomcat 的线程池有多努力吗?》


好的,前面两个知识点铺垫完成了


image.png


这个题,从线程池设计的角度,我会这样去回答:


前面我们说了,10 个机器,1000 个请求并发,平均每个服务承担 100 个请求。服务器是 4 核的配置。


那么如果是 CPU 密集型的任务,我们应该尽量的减少上下文切换,所以核心线程数可以设置为 5,队列的长度可以设置为 100,最大线程数保持和核心线程数一致。


如果是 IO 密集型的任务,我们可以适当的多分配一点核心线程数,更好的利用 CPU,所以核心线程数可以设置为 8,队列长度还是 100,最大线程池设置为 10。

当然,上面都是理论上的值。


我们也可以从核心线程数等于 5 开始进行系统压测,通过压测结果的对比,从而确定最合适的设置。


同时,我觉得线程池的参数应该是随着系统流量的变化而变化的。


所以,对于核心服务中的线程池,我们应该是通过线程池监控,做到提前预警。同时可以通过手段对线程池响应参数,比如核心线程数、队列长度进行动态修改。


上面的回答总结起来就是四点:


  1. CPU密集型的情况。


  1. IO密集型的情况。


  1. 通过压测得到合理的参数配置。


  1. 线程池动态调整。


前两个是教科书上的回答,记下来就行,面试官想听到这两个答案。


后两个是更具有实际意义的回答,让面试官眼前一亮。


基于这道面试题有限的信息,设计出来的线程池队列长度其实只要大于 100 就可以。

甚至还可以设置的极限一点,比如核心线程数和最大线程数都是 4,队列长度为 96,刚好可以承担这 100 个请求,多一个都不行了。


所以这题我觉得从这个角度来说,并不是要让你给出一个完美的解决方案,而是考察你对于线程池参数的理解和技术的运用。


面试的时候我觉得这个题答到这里就差不多了。


接下来,我们再发散一下。


比如面试官问:如果我们的系统里面没有运用线程池,那么会是怎么样的呢?


首先假设我们开发的系统是一个运行在 Tomcat 容器里面的,对外提供 http 接口的 web 服务。


系统中没有运用线程池相关技术。那么我们可以直接抗住这 100 个并发请求吗?

答案是可以的。


Tomcat 里面有一个线程池。其 maxThreads 默认值是 200(假定 BIO 模式):


image.png


在 BIO 的模式下,Tomcat 的默认配置,最多可以接受到 300 (200+100)个请求。再多就是连接拒绝,connection refused。


所以,你要说处理这 100 个并发请求,那不是绰绰有余吗?


但是,如果是每秒 100 个并发请求,源源不断的过来,那就肯定是吃不消了。


这里就涉及到两个层面的修改:


  1. Tomcat 参数配置的调优。


  1. 系统代码的优化。


针对 Tomcat 参数配置的调优,我们可以适当调大其 maxThreads 等参数的值。


针对系统代码的优化,我们就可以引入线程池技术,或者引入消息队列。总之其目的是增加系统吞吐量。


同理,假设我们是一个 Dubbo 服务,对外提供的是 RPC 接口。


默认情况下,服务端使用的是 fixed 线程池,核心线程池数和最大线程数都是 200。队列长度默认为 0:


image.png



目录
相关文章
|
14天前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
69 2
|
3月前
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
322 83
|
3月前
|
存储 Java 调度
Java虚拟线程:轻量级并发的革命性突破
Java虚拟线程:轻量级并发的革命性突破
300 83
|
5月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
207 0
|
5月前
|
设计模式 运维 监控
并发设计模式实战系列(4):线程池
需要建立持续的性能剖析(Profiling)和调优机制。通过以上十二个维度的系统化扩展,构建了一个从。设置合理队列容量/拒绝策略。动态扩容/优化任务处理速度。检查线程栈定位热点代码。调整最大用户进程数限制。CPU占用率100%
362 0
|
5月前
|
存储 缓存 安全
JUC并发—11.线程池源码分析
本文主要介绍了线程池的优势和JUC提供的线程池、ThreadPoolExecutor和Excutors创建的线程池、如何设计一个线程池、ThreadPoolExecutor线程池的执行流程、ThreadPoolExecutor的源码分析、如何合理设置线程池参数 + 定制线程池。
JUC并发—11.线程池源码分析
|
6月前
|
Java
线程池是什么?线程池在实际工作中的应用
总的来说,线程池是一种有效的多线程处理方式,它可以提高系统的性能和稳定性。在实际工作中,我们需要根据任务的特性和系统的硬件能力来合理设置线程池的大小,以达到最佳的效果。
167 18
|
8月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
140 26
|
8月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
147 17

热门文章

最新文章