首页 科技正文

保定火车站:面试问我,建立多少个线程合适?我该怎么说

admin 科技 2020-04-08 51 0

| 若是悦目,请给个赞

  • 你有一个头脑,我有一个头脑,我们交流后,一个人就有两个头脑

  • If you can NOT explain it simply, you do NOT understand it well enough

现陆续将Demo代码和手艺文章整理在一起 Github实践精选 ,利便人人阅读查看,本文同样收录在此,以为不错,还请Star


为什么要使用多线程?

防止并发编程失足最好的设施就是不写并发程序


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

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

我也很赞许这个谜底,但说的不够详细

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

若是问你选择多线程的缘故原由就是一个【快】字,面试也就不会出那么何等蛾子了。你有没有问过你自己

  1. 并发编程在所有场景下都是快的吗?

  2. 知道它很快,作甚快?怎样器量?

想知道这两个问题的谜底,我们需要一个从【定性】到【定量】的剖析历程

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

将这句话翻译到硬件级别就是要充实的行使 CPU 和 I/O 的行使率


两个准确获得保证,也就能到达最大化行使 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亿]

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


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

以是,单核CPU处置CPU密集型程序,这种情形并不太适合使用多线程

此时若是在 4 核CPU下,同样建立四个线程来分段盘算,看看会发生什么?


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

以是,若是是多核CPU 处置 CPU 密集型程序,我们完全可以最大化的行使 CPU 焦点数,应用并发编程来提高效率

I/O密集型程序

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

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

同样在单核 CPU 的情形下:


从上图中可以看出,每个线程都执行了相同长度的 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耗时)

我这么体贴,固然忧郁有些同砚不明白这个公式,我们将上图的比例手动带入到上面的公式中:


这是一个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章节】截图在此,人人有兴趣的可以自己看看


理论上来说,理论上来说,理论上来说,这样就能到达 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?

保定火车站:面试问我,建立多少个线程合适?我该怎么说  第1张

然则,然则,这是由于没有思量到CPU数目。家里又没矿,一样平常服务器的CPU核数为16或者32,若是有80个线程,那么肯定会带来太多不必要的线程上下文切换开销(希望这句话你可以自动说出来),这就需要调优了,来做到最佳 balance

小问二

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

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

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

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


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

由于一次请求不仅仅包罗 CPU 和 I/O操作,详细的调优历程还要思量内存资源,网络等详细内容

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

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

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


怎么明白这个公式呢?


这个结论告诉我们,如果我们的串行率是 5%,那么我们无论接纳什么手艺,最高也就只能提高 20 倍的性能。

若何简朴粗暴的明白串行百分比(实在都可以通过工具得出这个效果的)呢?来看个小 Tips:

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

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

最小化临界区局限,由于临界区的巨细往往就是瓶颈问题的所在,不要像乱用try catch那样一锅端

总结

多线程纷歧定就比但线程高效,好比赫赫有名的 Redis (后面会剖析),由于它是基于内存操作,这种情形下,单线程可以很高效的行使CPU。而多线程的使用场景一样平常时存在相当比例的I/O或网络操作

另外,连系小学数学题,我们已经领会了若何从定性到定量的剖析的历程,在最先没有任何数据之前,我们可以使用上文提到的经验值作为一个伪尺度,其次就是连系现实来逐步的调优(综合 CPU,内存,硬盘读写速率,网络状态等)了

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

灵魂追问

  1. 我们已经知道建立多少个线程合适了,为什么还要搞一个线程池出来?

  2. 建立一个线程都要做哪些事情?为什么说频仍的建立线程开销很大?

  3. 多线程通常要注意共享变量问题,为什么局部变量就没有线程安全问题呢?

  4. ......

下一篇文章,我们就来说说,你熟悉又生疏的线程池问题

参考

谢谢先辈们总结的精髓,自己所写的并发系列很多多少都参考了以下资料

  • Java 并发编程实战

  • Java 并发编程之美

  • 码出高效

  • Java 并发编程的艺术

  • ......

,

Sunbet

Sunbet www.monetary-reproduction.com Sunbet仅需短短几秒,全天24小时无休止无限制免费注册,sunbet欢迎您的光临!

版权声明

本文仅代表作者观点,
不代表本站Allbet的立场。
本文系作者授权发表,未经许可,不得转载。

评论