阿里面试:最佳线程数,如何确定?

尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、shein 希音、百度、网易的面试资格,遇到很多很重要的面试题:

如何确定系统的最佳线程数?

小伙伴 没有回答好,导致面试挂了。

这个是一个非常常见的面试题,考察的是线程池的基本功。

如何才能回答得很漂亮,才能 让面试官刮目相看、口水直流呢?这里,尼恩给大家做一下系统化、体系化的梳理,让面试官爱到 “不能自已、口水直流”,然后帮大家 实现 ”offer自由”

当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典》V174版本PDF集群,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

注:本文以 PDF 持续更新,最新尼恩 架构笔记、面试题 的PDF文件,请关注本公众号【技术自由圈】获取。

如何确定系统的最佳线程数?

首先看编程规范中, 有两个很重要的,与线程有关的需要强制执行的规范:

规范一:【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

说明: Java线程的创建非常昂贵,需要JVM和OS(操作系统)配合完成大量的工作:

1)消耗内存资源:必须为线程堆栈分配和初始化大量内存块,其中包含至少1MB的栈内存。

2)消耗CPU资源:需要进行系统调用,以便在OS(操作系统)中创建和注册内核线程,大量内核线程调度会导致CPU上下文过度切换。

所以,Java高并发应用频繁创建和销毁线程的操作将是非常低效的,而且是不被编程规范所允许的。

如何降低Java线程的创建成本?必须使用到线程池。使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。

以上的内容,在尼恩的 《Java 高并发核心编程 卷2》 进行了详细介绍。

规范二:【强制】线程池不允许使用Executors去创建快捷线程池 ,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明:Executors返回的线程池对象的弊端如下:

  • FixedThreadPool和SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
  • CachedThreadPool和ScheduledThreadPool: 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。

通过以上规范,说明我们应用中,需要用自定义线程池。 然而,由于构造一个线程池竟然有7个参数

在这里插入图片描述

7个重要参数中,最为重要的三个是:核心,最大线程数量, BlockingQueue。前两个参数和线程数量有关系, 后一个和内存资源消耗有关。

线程数设置太少或者阻塞队列太小, 会导致大量任务被拒绝,抛出RejectedExecutionException,触发线上的接口降级,用户体验很差。

二线程数设置太多或者阻塞队列太长,会导致资源消费高而有效负荷很小, 特别是阻塞队列设置过长,会导致频繁FullGC,甚至OOM。

确定系统的最佳线程数的3个step

如何确定系统的最佳线程数,大体上分三步:

第一步,理论预估;

第二步,压测验证;

第三步,监控调整。

在这里插入图片描述

这也是尼恩给大家归纳的,最为理想的: 可监控/可弹性的 线程池模式

step1: 完成线程数的理论预估 (设计阶段)

在尼恩的 《Java 高并发核心编程 卷2》 进行了详细介绍。

首先,按照任务类型对线程池进行分类, 分为三类,具体如下图:

在这里插入图片描述

具体,请参见在尼恩的 《Java 高并发核心编程 卷2》 1.7.1 小节。

第一类:IO 密集型线程池线程数预估

线程数就是 CPU的核数的2倍。

在这里插入图片描述

具体,请参见在尼恩的 《Java 高并发核心编程 卷2》 1.7.2 小节。

第二类:CPU密集线程池线程数预估

CPU密集型任务并行执行的数量应当等于CPU的核心数, 线程数就是 CPU的核数

在这里插入图片描述

具体,请参见在尼恩的 《Java 高并发核心编程 卷2》 1.7.3小节。

第三类:混合型线程池线程数预估

混合型线程池线程数预估, 参考下面的的公式:

最佳线程数 = ((线程等待时间 + 线程 CPU 时间) / 线程 CPU 时间 ) * CPU 核数

在这里插入图片描述

具体,请参见在尼恩的 《Java 高并发核心编程 卷2》 1.7.4小节。

step2: 完成线程数的压测验证 (设计阶段)

过少的线程会造成任务拒绝,业务降级。

过多的线程会造成,额外的内存开销CPU开销,甚至会导致OOM。

所以,合理的线程池线程数,才是王道。

在设计阶段完成了step1的线程数的理论预估之后, 那么我们的理论值就出来了。

如何做验证呢? 这里需要 压测。

根据公式:

服务器端最佳线程数量=((线程等待时间+线程cpu时间)/线程cpu时间) * cpu数量

前面线程等待时间,线程cpu时间都是 预估的 ,都是要验证的。

首先通过用户慢慢递增来进行性能压测,观察QPS。 持续大的增加用户数, 压测出最大的吞吐量。

然后再 收集 最大的吞吐量场景的 线程等待时间,线程cpu时间, 再计算出最佳线程数。

step3: 完成线程数的线上调整 (生产阶段)

压测的场景,是有限的。 而线上的业务, 是复杂的,多样的。

由于系统运行过程中存在的不确定性,很难一劳永逸地规划一个合理的线程数。

所以,需要进行生产阶段线程数的两个目标:

  • 可监控预警
  • 可在线调整

在这里插入图片描述

第一个维度:可监控预警

在这里插入图片描述

第二个维度:可在线调整

在这里插入图片描述

在线动态调整实操:结合Nacos 实现动态化线程池

优秀的动态化线程池轮子,主要有:

  • Hippo4J
  • dynamic-tp

如果线上使用,可以使用这些轮子项目。

但是尼恩的是[技术自由圈]一个实战社群,必须自己从0到1,去撸一把代码,提升自己的水平。

1.结合Nacos 实现动态化线程池架构

结合Nacos 实现动态化线程池的参数在线调整,架构如下:

在这里插入图片描述

2.Nacos 上的配置如下:

在这里插入图片描述

3.线程池配置和nacos配置变更监听

在这里插入图片描述

4.线程池配置的动态刷新

在这里插入图片描述

在这里插入图片描述

5.LinkedBlockingQueue 实现resize

LinkedBlockingQueue 不支持 resize, 需要重新定制。自定义可以扩容的 LinkedBlockingQueue ,结构如下:

在这里插入图片描述

这里采用的是读写锁,对capacity 的设置,进行线程安全 保护:

在这里插入图片描述

读写锁的使用如下:

在这里插入图片描述

通过对capacity的安全修改,以达到动态扩展目的。

其他代码和LinkedBlockingQueue代码一致。

在线动态监控实操:结合PGA实现Metric采集和预警

先把架构图画出来,大致如下:

在这里插入图片描述

具体的实现细节,留到 《尼恩java面试宝典》 配套视频里边,慢慢介绍哈。

《尼恩java面试宝典》 ,即将一个专题一个专题的开始录制视频了。

说在最后

线程相关的面试题,是非常常见的面试题。

以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典》V174,在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

另外,如果没有面试机会,可以找尼恩来帮扶、领路。

尼恩已经指导了大量的就业困难的小伙伴上岸,前段时间,帮助一个40岁+就业困难小伙伴拿到了一个年薪100W的offer,小伙伴实现了 逆天改命 。

尼恩技术圣经系列PDF

  • 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
  • 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
  • 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
  • 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
  • 《大数据HBase学习圣经:一本书实现HBase学习自由》
  • 《大数据Flink学习圣经:一本书实现大数据Flink自由》
  • 《响应式圣经:10W字,实现Spring响应式编程自由》
  • 《Go学习圣经:Go语言实现高并发CRUD业务开发》

……完整版尼恩技术圣经PDF集群,请找尼恩领取

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/493429.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL注入漏洞解析--less-5

1.进入第五关我们先看提示 2.还是说让我们输入一个id数字,那我们就输入一个先看一下 3.根据页面结果得知虽然有显示,但是和前面四关还是不一样是因为页面虽然有东西。但是只有对于请求出错显示,其余的就没有了。这个时候我们用联合查询就没有…

数据安全治理实践路线(中)

数据安全建设阶段主要对数据安全规划进行落地实施,建成与组织相适应的数据安全治理能力,包括组织架构的建设、制度体系的完善、技术工具的建立和人员能力的培养等。通过数据安全规划,组织对如何从零开始建设数据安全治理体系有了一定认知&…

linux提权之sudo风暴

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 …

算法--贪心

这里写目录标题 区间问题区间选点引入算法思想例题代码 最大不相交区间的数量算法思想例题代码 区间分组算法思想例题代码 一级目录二级目录二级目录二级目录 区间问题 区间选点 引入 区间问题会给定几个区间,之后要求我们在数轴上选取尽量少的点,使得…

[NOIP2011 普及组] 数字反转

AC代码&#xff1a; #include<iostream>using namespace std;int main() {long long n;cin >> n;long long temp n;long long sum 0;while(temp ! 0){int c temp % 10;sum sum * 10 c;temp temp / 10;}printf("%lld",sum);return 0; }

11个Linux性能分析命令

Linux性能分析命令有很多&#xff0c;不同的命令可以用来监控不同的系统资源和活动。根据您的问题&#xff0c;我为您推荐以下11个常用的Linux性能分析命令&#xff1a; uptime&#xff1a;显示系统的运行时间和平均负载。dmesg&#xff1a;显示系统的启动信息和内核的日志信息…

函数——递归6(c++)

角谷猜想 题目描述 日本一位中学生发现一个奇妙的 定理&#xff0c;请角谷教授证明&#xff0c;而教授 无能为力&#xff0c;于是产生了角谷猜想。 猜想的内容&#xff1a;任给一个自然数&#xff0c; 若为偶数则除以2&#xff0c;若为奇数则乘 3加1&#xff0c;得到一个新的…

Gitlab 设置页面语言为简体中文

1.用户登录&#xff0c;点击头像&#xff0c;再点击Preferences&#xff08;偏好设置&#xff09; 2.向下滑动&#xff0c;找到 Localization&#xff08;本地化&#xff09;&#xff0c;进行修改&#xff0c;并保存 3.刷新页面&#xff0c;就更改成简体中文了

亿道丨三防平板电脑厂家丨三防平板PDA丨三防工业平板:数字时代

在当今数字化时代&#xff0c;我们身边的世界变得越来越依赖于智能设备和无线连接。其中&#xff0c;三防平板PDA&#xff08;Personal Digital Assistant&#xff09;作为一种功能强大且耐用的数字工具&#xff0c;正在引领我们进入数字世界的全新征程。 三防平板PDA结合了平板…

基于 ResNet50和 SVM + 决策树的人脸口罩检测

欢迎收看&#xff0c;这篇文章是关于我如何使用 ResNet50作为特征提取器来构建掩码检测&#xff0c;然后使用支持向量机(SVM) 决策树和叠加集成方法作为分类器的一个快速解释。 为了向研究人员致敬&#xff0c;这个应用程序是基于研究论文&#xff0c;题目是“在2019冠状病毒…

什么是DOM?(详解)

什么是DOM&#xff1f; DOM的定义知识回顾什么是D&#xff1f;什么是O&#xff1f;什么是M&#xff1f;什么是DOM树&#xff1f;根节点对象与节点对象 DOM树简单举例DOM的主要用途 DOM的定义 DOM&#xff08;Document Object Model&#xff0c;文档对象模型&#xff09; W3C对…

系统性能提升70%!华润万家某核心系统数据库升级实践

华润万家是华润集团旗下优秀零售连锁企业&#xff0c;业务覆盖中国内地及香港市场&#xff0c;面对万家众多业务需求和互相关联的业务环境&#xff0c;亟需加强各业务耦合性&#xff0c;以适应线上、线下、物流、财务等各个业务环境的快速发展。 随着信息技术的快速发展和数字化…