1.1.2 多线程带来的问题
本节讨论的多线程带来的问题是针对Java语言层面的,硬件和系统层面的问题不进行深入讨论。
1.共同工作产生的问题
这里可以用现实中工作的例子做一个比喻,例如共有1000块砖,需要搬到A地点100块,需要搬到B地点200块。
如果只有一个工人做,则只需记住自己搬的数量和需要的总量就可以完成任务。
如果由多个工人同时做,则彼此就需要沟通协调才能完成任务。如果沟通协调出现问题就会导致任务失败,例如数量多了或者少了都是失败。这种现实中的例子实际还是比较简单的,在Java多线程的世界中,需要考虑更多的可能性,接下来会详细介绍。
2.线程上下文切换带来的性能损耗
线程上下文切换是单核、多核CPU都会存在的问题。所谓上下文切换,就好比在做一个任务A时,突然接收到任务B的信息要马上处理,这时肯定需要把任务A相关的信息进行缓存,以便后续再回到任务A时能继续处理任务A的工作,这个就是上下文切换。由系统来调度CPU的执行,上下文切换过多会造成CPU性能浪费。目前偏标准的一个做法是创建的线程数量最好是CPU核心数量的2倍或3倍,这个是一个偏理想的值。
1)CPU密集型程序
一个计算型的应用程序,CPU使用率非常高,当多线程并发执行时,可以充分利用CPU所有的核心数量,例如8核心的CPU,开8个线程执行时,在理想情况下此时的效率最高,有效减少CPU上下文切换所带来的性能损耗,因此对于CPU密集型的任务,线程数量在理想情况下等于CPU核心数量是最好的。
2)I/O密集型程序
I/O密集型程序是指以文件交互或者网络传输为主的程序,执行这种程序时CPU会有大量的时间处于等待任务的状态,这时可以适当提高线程数量,以保证CPU核心的最大利用率,例如8核心的CPU,可以开40个线程或者更多的线程,可视情况而定。
Linux无任务下的默认线程数量,如图1-1所示。
图1-1 Linux无任务下的默认线程数