关于多线程线程数如何设置的一点思考

一、为什么要采用多线程?

举个去饭店吃饭的例子,假设饭店里只有一个服务员,这个服务员每次只能服务一桌顾客,那么后来的顾客就只能等前面的顾客结束用餐后才能进行就餐,这样导致好多顾客等不及就去了别家。老板为了挽回这种局面,就额外聘请了其他几个服务员。这样一来,每次饭店就能同时服务之前好几倍的客人了。老板看到客流量大大增加,虽然需要另外付出几个服务员的工资,但是相较于总体收入来说,提升的收益远大于付出。这个例子里的服务员其实就相当于一个线程,提供读写、计算能力。在单线程模式下,任务都是串行执行的,前一个任务执行完才能执行下一个任务,简答的说,这种方式的效率很低下,最简单的解决办法就是,找一种方法可以同时执行多个任务,这就是多线程的来源。

二、线程数是不是越多越好呢?

既然多线程可以提高任务执行的效率,那么是不是线程数越多,效率提升的越明显呢?同样采用饭店的例子来说,前期可能多请几个服务员会使饭店的收益明显提升,但是想通过继续招聘服务员的方式来持续扩大营业额就会有点不切实际。思考一下:即使招聘了足够多的服务员,每个顾客过来都能有自己的专属服务员,是不是就能提高饭店的产出效率呢?当然不是,即使每个服务员收到了顾客的下单后立即反馈到后厨,后厨的厨师也不一定能马上做好相应的饭菜,做完每一份饭菜也是需要一定时间的。那这种情况下想要提高产出效率就只能再招聘更多的厨师了。这里的厨师其实对应饭店本身的处理能力,也就是我们常说的硬件资源。单纯的通过招聘服务员(提升线程数),受到饭店本身处理能力的限制,其实是不会再对效率有显著的提升。相反,招聘更多的服务员反而会消耗更多的工资。

三、不同场景下的方案

线程的本质都是在处理一些事情。这些事情按特点可划分为io密集型和CPU密集型。简言之,io密集型程序主要用于io的读写,比如文件的读写;而cpu密集型程序主要用作计算,比如循环、递归等计算处理过程。那么这两种类型的程序应该如何设置线程数才能使效率最大化呢?下面分开叙述:

1. IO密集型程序

io密集型程序的主要耗时在相关io的操作上,以阻塞性io为例(这里不展开讲io的类型),io的耗时主要在于数据的准备等待及写入。这个时间相较于cpu的处理时间通常是要更多的。我们设置最优线程数的目的就是希望能够同时处理多个事情,避免相互之间的等待,最好是io处理的线程和cpu处理的线程同时结束就完美了。基于这个考虑,我们可以归纳出一个数学模型:假设io处理的时间为to,cpu处理的时间为tu,io线程数为1,那么基于io和cpu同时处理完成的考虑,cpu的线程数即为to/tu,另外由于cpu可能有多个核心,所以最终合适的线程总数为(1+to/tu)*cpu核心数

2. cpu密集型程序

cpu密集型程序主要考虑cpu的计算时间,多个核心的线程可并行执行,所以合适的线程数应该为cpu核心数,考虑到线程阻塞等异常情况的影响,可以设定为cpu核心数+1

四、总结

线程数量不是越多越好,总会有一个较优的值区间,而且这个线程数的设定也不能一概而论,要针对具体的线程类型来考虑,本文基于io密集型和cpu密集型线程分别给出估算最优线程数的思考过程,记录也是为了更好的思考。

你可能感兴趣的:(关于多线程线程数如何设置的一点思考)