CPU与线程
在Java中,创建一个线程很简单,
new Thread()
就可以了,然后启动这个线程的话,调用它的strat()
方法。可是,调用这个方法之后,并不是立即启动线程,而是等待CPU的调度,获得CPU资源后才开始执行。所以说,CPU资源是线程运行的关键。
并行与并发
并行与并发的概念应该很多地方都介绍过, 我画了一张图。
并行与并发.jpg
这样介绍应该就比较清楚了。那么考虑一下,如果只有一个CPU(也就是单核CPU)能不能达到并行执行?显然是不可能的吧,一个CPU在同一时刻,只能把资源分配给一个任务,只有多核CPU时代的到来,才实现了并行执行的方式。所以很多资料上讲的并行与并发区别的关键词是,同一时刻和同一时间间隔。
单核CPU下的串行与并发
那么,再考虑一个问题,如果目前的环境是单核CPU,多线程编程还有没有必要?从上面的图中我们可以看出,如果是单核CPU的话,只能做到并发执行,而且,比串行执行的速度要快一些。可是,如果每个任务都去掉了等待时间的部分,那么在单核的环境下,串行执行是不是就跟并发执行的速度是一样的呢?
其实不是的,可能有人会听说过,线程的切换会有性能损耗。因为在实际的环境中,每个线程得到CPU的资源是有时间限制的,称为时间片,当一个线程的时间片用完后,会切换到另一个线程,可是当这个线程再次得到CPU资源的时候,会从上一次的位置继续向下执行,那它怎么就知道自己上一次的执行位置呢?所以就需要CPU做额外的工作,带来的性能的损耗。
所以说,在单核环境下,串行执行(单线程)速度快还是并发执行(多线程)速度快,要取决于任务是否有休眠时间。那么,在实际的环境中,休眠的操作就可以看作读/取文件的IO操作。所以说,没有休眠时间(或者时间相对较少)的任务,我们称之为计算密集型(CPU密集型)任务,有休眠时间(时间相对较多)的操作称为IO密集型任务。
总结:计算密集型任务适合串行执行,IO密集型任务适合并发执行。类比到我们当前的多核环境中也是适用的。
就比如一个常见的问题,线程池中的线程数规定多少才合适?想必这个问题大家心里应该有数了吧,先确定任务是计算密集型还是IO密集型,如果是前者,那就规定成当前CPU的核心数;如果是后者,可以是当前CPU的核心数 * 2。这只是个大概的数字,真实环境中还需要根据场景进行压测才能确定。
网友评论