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



目录
相关文章
|
1月前
|
安全
List并发线程安全问题
【10月更文挑战第21天】`List` 并发线程安全问题是多线程编程中一个非常重要的问题,需要我们认真对待和处理。只有通过不断地学习和实践,我们才能更好地掌握多线程编程的技巧和方法,提高程序的性能和稳定性。
148 59
|
1月前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
105 38
|
12天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
24天前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
1月前
|
Java
线程池内部机制:线程的保活与回收策略
【10月更文挑战第24天】 线程池是现代并发编程中管理线程资源的一种高效机制。它不仅能够复用线程,减少创建和销毁线程的开销,还能有效控制并发线程的数量,提高系统资源的利用率。本文将深入探讨线程池中线程的保活和回收机制,帮助你更好地理解和使用线程池。
59 2
|
1月前
|
Prometheus 监控 Cloud Native
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
73 4
|
1月前
|
Prometheus 监控 Cloud Native
在 Java 中,如何使用线程池监控以及动态调整线程池?
【10月更文挑战第22天】线程池的监控和动态调整是一项重要的任务,需要我们结合具体的应用场景和需求,选择合适的方法和策略,以确保线程池始终处于最优状态,提高系统的性能和稳定性。
131 2
|
2月前
|
Java
【编程进阶知识】揭秘Java多线程:并发与顺序编程的奥秘
本文介绍了Java多线程编程的基础,通过对比顺序执行和并发执行的方式,展示了如何使用`run`方法和`start`方法来控制线程的执行模式。文章通过具体示例详细解析了两者的异同及应用场景,帮助读者更好地理解和运用多线程技术。
29 1
|
2月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
48 1
C++ 多线程之初识多线程
|
2月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
20 3