Java的并发策略


首先,说起并发技术,都要先知道IO密集型和CPU密集型。那么这两种密集型的概念是怎样的呢?简单的说,就是凡事涉及大量计算的,而少数时间只花在读取IO数据的为CPU密集型,因为大量的运行只有在CPU才能进行。而凡是只需要CPU一个命令,实现如内存或硬盘的IO读写操作,而CPU根本无需或者少量计算的,就是属于IO密集型。或者这么说,如果任务被阻塞的时间少于50%,则这些任务是CPU密集型的,若任务被阻塞的时间大于执行的时间,即该任务是IO密集型的。

接下来我们就可以针对这两种类型来讨论并发策略了。

一般情况下,通过使用多线程来进行并发处理。那么,多少线程数才能达到最佳效果呢?一般计算程序所需要的线程总数如下:

线程数=CPU可用核数/(1-阻塞系数),其中阻塞系数的取值在0和1之间。一般,CPU密集型的阻塞系数为0,所以一般情况下,CPU密集型的线程数只和CPU可用核数相关。而IO密集型任务的阻塞系数则接近1.

在IO密集型应用程序中使用并发技术:

在IO密集型应用程序中,线程数的多少受到子任务总数的影响。如在程序中划分子任务的代码如下:

final ExecutorService excutorPool = Executors.newFixedThreadPool(poolSize);

即子任务的个数有变量poolSize决定,如poolSize的大小为40,即任务划分成40个子任务,则在一个单核处理上开40个线程或者在一个双核处理器上开20个线程就可以了,总线程数超过40个对程序速度替身没有多大的效果。

而我们或许有疑问,为什么不增大子任务的个数呢?这个是资源问题,任何东西资源都是有限的。

在CPU密集型应用程序中使用并发技术:

典型的属于CPU密集型应用程序的就是给出个,判断是否为素数。这种程序需要计算机大量的计算,占据CPU处理的时间比较长,特别是给出两个数的,计算这两个数之间有哪些数是素数。这种CPU密集型应用程序使用的线程数受到子任务的束缚,而子任务是受到CPU核的束缚。即如果是双核的,那么总线程数为2。另外还要考虑到划分任务时工作负载均匀分布。如计算两个数之间有哪些素数,若只是普通的平均分一半,则另一半因为数值太大,CPU所处理的时间就会比前一部分慢,所以考虑工作负载的均匀性是很重要的。

CPU密集型的几点重要经验:

1.子任务的划分数应不少于处理器核心数。

2.线程数多于处理器核心数对性能提升是毫无帮助的。

3.在子任务划分数超过一定的数量之后,再增加子问题华分数对性能的提升将十分有限。

并发遍历二叉树 Java 实现

Java并发编程下变量可见行分析

Java并发编程总结---Hadoop核心源码实例解读

Java并发包中的几种ExecutorService

Java多线程之并发锁

相关内容