前端的请求最大线程数是多少啊_面试官:创建多少个线程合适,我该怎么说?...

转载:https://mp.weixin.qq.com/s/j5d4Jtxo0RgJWgpnG9HxlQ

36a0a9ea14a1e80532952472bbc4a54f.png

为什么要使用多线程?

防止并发编程出错最好的办法就是不写并发程序

7e79147090c0166e30918390564d8823.gif

既然多线程编程容易出错,为什么它还经久不衰呢?

A:那还用说,肯定在某些方面有特长呗,比如你知道的【它很快,非常快】

我也很赞同这个答案,但说的不够具体

并发编程适用于什么场景?

如果问你选择多线程的原因就是一个【快】字,面试也就不会出那么多幺蛾子了。你有没有问过你自己

  1. 并发编程在所有场景下都是快的吗?
  2. 知道它很快,何为快?怎样度量?

想知道这两个问题的答案,我们需要一个从【定性】到【定量】的分析过程

使用多线程就是在正确的场景下通过设置正确个数的线程来最大化程序的运行速度(我感觉你还是啥也没说)

将这句话翻译到硬件级别就是要充分的利用 CPU 和 I/O 的利用率

4a49e894455429b4dd4ca9cb4a8e824c.png

两个正确得到保证,也就能达到最大化利用 CPU 和 I/O的目的了。最关键是,如何做到两个【正确】?

在聊具体场景的时候,我们必须要拿出我们的专业性来。送你两个名词 buff 加成

  • CPU 密集型程序
  • I/O 密集型程序

CPU 密集型程序

一个完整请求,I/O操作可以在很短时间内完成, CPU还有很多运算要处理,也就是说 CPU 计算的比例占很大一部分

假如我们要计算 1+2+....100亿 的总和,很明显,这就是一个 CPU 密集型程序

在【单核】CPU下,如果我们创建 4 个线程来分段计算,即:

  1. 线程1计算 [1,25亿)
  2. ...... 以此类推
  3. 线程4计算 [75亿,100亿]

我们来看下图他们会发生什么?

f8502e4f1d9c8cdfe51e7ba9accd3c04.png

由于是单核 CPU,所有线程都在等待 CPU 时间片。按照理想情况来看,四个线程执行的时间总和与一个线程5独自完成是相等的,实际上我们还忽略了四个线程上下文切换的开销

所以,单核CPU处理CPU密集型程序,这种情况并不太适合使用多线程

此时如果在 4 核CPU下,同样创建四个线程来分段计算,看看会发生什么?

330be7df8b4900c4eabdf242f25881ce.png

每个线程都有 CPU 来运行,并不会发生等待 CPU 时间片的情况,也没有线程切换的开销。理论情况来看效率提升了 4 倍

所以,如果是多核CPU 处理 CPU 密集型程序,我们完全可以最大化的利用 CPU 核心数,应用并发编程来提高效率

I/O密集型程序

与 CPU 密集型程序相对,一个完整请求,CPU运算操作完成之后还有很多 I/O 操作要做,也就是说 I/O 操作占比很大部分

我们都知道在进行 I/O 操作时,CPU是空闲状态,所以我们要最大化的利用 CPU,不能让其是空闲状态

同样在单核 CPU 的情况下:

4ece948a-8063-4aa6-8d1b-56f535beca93

从上图中可以看出,每个线程都执行了相同长度的 CPU 耗时和 I/O 耗时,如果你将上面的图多画几个周期,CPU操作耗时固定,将 I/O 操作耗时变为 CPU 耗时的 3 倍,你会发现,CPU又有空闲了,这时你就可以新建线程 4,来继续最大化的利用 CPU。

综上两种情况我们可以做出这样的总结:

线程等待时间所占比例越高,需要越多线程;线程CPU时间所占比例越高,需要越少线程。

到这里,相信你已经知道第一个【正确】使用多线程的场景了,那创建多少个线程是正确的呢?

创建多少个线程合适?

面试如果问到这个问题,这可是对你理论和实践的统考。想完全答对,你必须要【精通/精通/精通】小学算术

从上面知道,我们有 CPU 密集型和 I/O 密集型两个场景,不同的场景当然需要的线程数也就不一样了

CPU 密集型程序创建多少个线程合适?

有些同学早已经发现,对于 CPU 密集型来说,理论上 线程数量 = CPU 核数(逻辑) 就可以了,但是实际上,数量一般会设置为 CPU 核数(逻辑)+ 1, 为什么呢?

《Java并发编程实战》这么说:

计算密(CPU)集型的线程恰好在某时因为发生一个页错误或者因其他原因而暂停,刚好有一个“额外”的线程,可以确保在这种情况下CPU周期不会中断工作。

所以对于CPU密集型程序, CPU 核数(逻辑)+ 1 个线程数是比较好的经验值的原因了

I/O密集型程序创建多少个线程合适?

上面已经让大家按照图多画几个周期(你可以动手将I/O耗时与CPU耗时比例调大,比如6倍或7倍),这样你就会得到一个结论,对于 I/O 密集型程序:

最佳线程数 = (1/CPU利用率) = 1 + (I/O耗时/CPU耗时)

我这么体贴,当然担心有些同学不理解这个公式,我们将上图的比例手动带入到上面的公式中:

04a0b4b0f88c5b051f8bcf0069769507.png

这是一个CPU核心的最佳线程数,如果多个核心,那么 I/O 密集型程序的最佳线程数就是:

最佳线程数 = CPU核心数 * (1/CPU利用率) = CPU核心数 * 1 + (I/O耗时/CPU耗时)

说到这,有些同学可能有疑问了,要计算 I/O 密集型程序,是要知道 CPU 利用率的,如果我不知道这些,那要怎样给出一个初始值呢?

按照上面公式,假如几乎全是 I/O耗时,所以纯理论你就可以说是2N(N=CPU核数),当然也有说 2N + 1的,(我猜这个 1 也是 backup),没有找到具体的推倒过程,在【并发编程实战-8.2章节】截图在此,大家有兴趣的可以自己看看

f3243489e9c2e97b4c42d8430583b825.png

理论上来说,理论上来说,理论上来说,这样就能达到 CPU 100% 的利用率

如果理论都好用,那就用不着实践了,也就更不会有调优的事出现了。不过在初始阶段,我们确实可以按照这个理论之作为伪标准, 毕竟差也可能不会差太多,这样调优也会更好一些

谈完理论,咱们说点实际的,公式我看懂了(定性阶段结束),但是我有两个疑问:

  1. 我怎么知道具体的 I/O耗时和CPU耗时呢?
  2. 怎么查看CPU利用率?

没错,我们需要定量分析了

幸运的是,我们并不是第一个吃螃蟹的仔儿,其实有很多 APM (Application Performance Manager)工具可以帮我们得到准确的数据,学会使用这类工具,也就可以结合理论,在调优的过程得到更优的线程个数了。我这里简单列举几个,具体使用哪一个,具体应用还需要你自己去调研选择,受篇幅限制,暂不展开讨论了

  1. SkyWalking
  2. CAT
  3. zipkin

上面了解了基本的理论知识,那面试有可能问什么?又可能会以怎样的方式提问呢?

面试小问

小问一

假设要求一个系统的 TPS(Transaction Per Second 或者 Task Per Second)至少为20,然后假设每个Transaction由一个线程完成,继续假设平均每个线程处理一个Transaction的时间为4s

如何设计线程个数,使得可以在1s内处理完20个Transaction?

c3ade643e267427654daccd3d8d2307a.png

但是,但是,这是因为没有考虑到CPU数目。家里又没矿,一般服务器的CPU核数为16或者32,如果有80个线程,那么肯定会带来太多不必要的线程上下文切换开销(希望这句话你可以主动说出来),这就需要调优了,来做到最佳 balance

小问二

计算操作需要5ms,DB操作需要 100ms,对于一台 8个CPU的服务器,怎么设置线程数呢?

如果不知道请拿三年级期末考试题重新做(今天晚自习留下来),答案是:

线程数 = 8 * (1 + 100/5) = 168 (个)

那如果DB的 QPS(Query Per Second)上限是1000,此时这个线程数又该设置为多大呢?

77f56fe4c28889640852fd71a2dfd9c7.png

同样,这是没有考虑 CPU 数目,接下来就又是细节调优的阶段了

因为一次请求不仅仅包括 CPU 和 I/O操作,具体的调优过程还要考虑内存资源,网络等具体内容

增加 CPU 核数一定能解决问题吗?

看到这,有些同学可能会认为,即便我算出了理论线程数,但实际CPU核数不够,会带来线程上下文切换的开销,所以下一步就需要增加 CPU 核数,那我们盲目的增加 CPU 核数就一定能解决问题吗?

在讲互斥锁的内容是,我故意遗留了一个知识:

30b6dba63f72200061c1851693ff7ebd.png

怎么理解这个公式呢?

8387a5985dda724de9986b675864947e.png

这个结论告诉我们,假如我们的串行率是 5%,那么我们无论采用什么技术,最高也就只能提高 20 倍的性能。

如何简单粗暴的理解串行百分比(其实都可以通过工具得出这个结果的)呢?来看个小 Tips:

Tips: 临界区都是串行的,非临界区都是并行的,用单线程执行临界区的时间/用单线程执行(临界区+非临界区)的时间就是串行百分比

现在你应该理解我在讲解 synchronized 关键字时所说的:

最小化临界区范围,因为临界区的大小往往就是瓶颈问题的所在,不要像乱用try catch那样一锅端

总结

多线程不一定就比但线程高效,比如大名鼎鼎的 Redis (后面会分析),因为它是基于内存操作,这种情况下,单线程可以很高效的利用CPU。而多线程的使用场景一般时存在相当比例的I/O或网络操作

另外,结合小学数学题,我们已经了解了如何从定性到定量的分析的过程,在开始没有任何数据之前,我们可以使用上文提到的经验值作为一个伪标准,其次就是结合实际来逐步的调优(综合 CPU,内存,硬盘读写速度,网络状况等)了

最后,盲目的增加 CPU 核数也不一定能解决我们的问题,这就要求我们严格的编写并发程序代码了

灵魂追问

  1. 我们已经知道创建多少个线程合适了,为什么还要搞一个线程池出来?
  2. 创建一个线程都要做哪些事情?为什么说频繁的创建线程开销很大?
  3. 多线程通常要注意共享变量问题,为什么局部变量就没有线程安全问题呢?

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

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

相关文章

php打印出函数的内容吗,PHP打印函数集合详解以及PHP打印函数对比详解(精)

1 echo();2 print();3 die();4 printf();5 sprintf();6 print_r();7 var_dump(); 1 echo() 可以同时输出多个字符串,可以多个参数,并不需要圆括号,无返回值。 2 print() 只可以同时输出一个字符串,一个参数,需要圆括号,有返回值,当其执行失败时返flase .prin1 echo(…

正则表达式(1)

字符转义 大多数重要的正则表达式语言运算符都是非转义的单个字符。转义符 \(单个反斜杠)通知正则表达式分析器反斜杠后面的字符不是运算符。例如,分析器将星号 (*) 视为重复限定符,而将后跟星号的反斜杠 (\*) 视为 Unicode 字符 …

百度地图infowindow的close事件_百度地图蒙圈:车主要加油误导母婴店 跑偏理由令人啼笑皆非...

常在江湖飘,哪有不挨刀。经常驾车出门在外的您,有过被导航坑的经历么?其实在早些年手机导航刚刚兴起的时候,这类现象确实比较常见,但是到了如今大数据的时代,手机导航数据更新比较及时,问题已经…

Linux中后台执行scp

最近在一台远程机器上scp一个大文件,需要大半天才能完全down下来,用xshell工具执行完命令之后还不能关闭,否则的话就停止了,我的本本还不能一直放这开xshell。就想到nohup,但是scp命令输入密码是提示的,不能…

质量效能研发部php,【百度】百度质量效能研发部【社招/实习】

职位:百度质量效能研发部【社招/实习】-百度【岗位职责】C研发工程师 / iOS∧orid 开发工程师 / 平台开发工程师 / 算法工程师(智能测试方向) base 上海、北京 本次招录面向各程序栈的优秀同学们,开放社招及实习入口,四类方向供大家选择&…

商业模式新生代_业务分析基础 - 商业模式新生代01篇

商业模式画布商业模式新生代由亚历山大奥斯特瓦德(Alexander Osterwalder)和伊夫皮尼厄(Yves Pigneur)编写,发表于2016年。该书提出了商业模式画布模型,既可以用于创业公司(Start-ups&#xff0…

yum 安装 sun java,CentOS yum安装sun Java jre jdk和openjdk

在Linux下的tty终端下,安装sun jre,但是去Oracle安装,下载居然还要登录,使用cookie,没办法。直接到http://www.java.com/下载了。说明:如果使用yum install 安装软件,具体的软件名称不知道&…

CodePage简介(转)

CodePage简介(转) 1. Codepage的定义和历史 字符内码(charcter code)指的是用来代表字符的内码.读者在输入和存储文档时都要使用内码,内码分为 单字节内码 -- Single-Byte character sets (SBCS),可以支持256个字符编码. 双字节内码 -- Double-Byte character sets)(DBCS),可…

折半查找和二叉排序树的时间性能_leecode刷题----二分搜索与二叉查找(排序)树...

预备知识:二分查找已知一个排序数组A,如A[-1,2,5,20,90,100,207,800],另外一个乱序数组B,如B[50,90,3,-1,2-7,80],求B中任意某个元素是否在A中出现,结果存储在数组C中,出现用1代表,未出现用0代表…

php pacs,DICOM医学图像处理:WEB PACS初谈四,PHP DICOM Class – 只要踏出一步,路就在前方——zssure – CSDN博客...

背景:预告了好久的几篇专栏博文一直没有整理好,主要原因是早前希望搭建的WML服务器计划遇到了问题。起初以为参照DCMTK的官方文档wwwapp.txt结合前两天搭建的WAMP服务器可以顺利的实现WML服务,借此就可以同时完成WEB PACS系列以及搭建Dicom W…

COM, COM+ and .NET 的区别

所有的优秀程序员都会尽自己的最大努力去使自己所写的程序具有更好的可重用性,因为它可以让你快速地写出更加健壮和可升级性的程序。   有两种使代码重用的选择:  1.白盒:最简单的一种,就是把你的程序片拷贝到另一…

mfc在运行的时候为什么没有实例化_为什么不建议把数据库部署在Docker容器内?...

本文同步Java知音社区,专注于Java原文:https://www.toutiao.com/i6805798581971190276/近2年Docker非常的火热,各位开发者恨不得把所有的应用、软件都部署在Docker容器中,但是您确定也要把数据库也部署的容器中吗?这个…

php 获取指定时间 次日,PHP时间判断语句

用php只能获取服务器端的时间,得用js获取客户端时间,然后生成对应的css文件内容。为了确保页面能正确显示,还得有个默认的css文件链接。示例代码如下:function DynamicLoad(){var Selfthis; //对象自身//功能:加载指定…

泛型的优势

假设需要一个两个整形变量交换的函数,我们很快就可以嗒嗒嗒嗒的敲出下面的 Swap 函数:void Swap(ref int lhs, ref int rhs){int temp lhs;lhs rhs;rhs temp;}随着项目进展,我们发现,需要用到 Swap 函数的不仅是整形,变量 还有…

老男孩python全栈开发视频教程_老男孩Python全栈开发(92天全)视频教程 自学笔记08...

day8课程内容:文件操作fopen(小重山,r,encodingutf8)     #以读的方式打开文件dataf.read()print(data)f.close() #关闭文件句柄fopen(小重山2,w,encodingutf8)    #以清空再写 的方式打开文件,这一步就将文件以前的内容清空了,如果…

php echo 后必须die,die 提示的消息都去哪了?

小弟新手:$fpfopen("./readme.txt","r") or die("不能打开该文件");想问下,如果打开失败,那么die 的这条消息输出到哪了啊?貌似打开失败界面也没有直接弹出这条消息?请问使用die这条消息…

BSTR、char* 和 CString 之间的转换 (转)

BSTR、char* 和 CString 之间的转换 (1) char*转换成CString 若将char*转换成CString,除了直接赋值外,还可使用CString::Format进行。例如: char chArray[] "This is a test"; char * p "This is a test"; 或 LPSTR …

python打开音频文件_Python处理音频文件的实用姿势

每天叫醒我的不是理想,是楼下广场舞的音乐。音乐是人类的通用语言,不分国界不分种族。抖音短视频爆火的关键因素之一,就是普通人也能便捷地使用BGM表达自我。从感性角度看,音乐可以有很多种解释,如:音乐是有…

java三路快排,java二路快排很慢

老师,以下是我二路快排的java代码public class quickSortTwoway {public quickSortTwoway() {};public static void quickSort(Integer[] arr) {__quickSort(arr, 0, arr.length - 1);}private static void __quickSort(Integer[] arr, int l, int r) {if(l > r)…

Web开发常出现的错误[个人收集]

获取DataGrid中的每行中的第一行的第一个textbox (有点老,但用的到) publicabstractclassHelper { publicclassConvert { publicstaticTextBox ToTextBox(Control control) { TextBox tb control asTextBox; …