先举个例子说明一下并行和并发:
假设:有8辆车(8核处理器)、8堆货物(8个应用) 并行:用8辆车在同一时刻上开始去拉这8堆货物,相当于每车拉一堆。 并发:用1辆车在某个时间段去拉这8堆货物,轮流着拉,先拉一段货物A、再拉一段货物B、再拉货物A、再 拉货物B,依次循环
sequential():可将并行流修改为顺序流。
parallel():将顺序流修改为并行流。
在java8中,stream并行流就是一个把内容分割成多个数据块,再用不同的线程去分别处理每个数据块的处理方式。在并行流内部使用的是ForkJoinPool(分支/合并框架),其中默认的线程数量就是你当前机器的处理器数量。
虽然stream具有并行的功能,但也并不是每次都使用并行执行效率会更高,对于流的并行化执行也是需要消耗资源的。对于并行化来说,其执行时本身就需要对流做递归划分,把每个子流的规约操作分配到不同线程上,然后把这些操作的结果再合并成一个值,就这需要数据在多个内核之间移动,所以当数据量很小时并行处理所带来的好处还比不上并行化所造成的额外开销大,也就是说并行流并不总是比顺序流快,是需要前提条件的。
在处理装箱和拆箱操作时,也尽量使用原始类型的流(IntStream/LongStream等)来减少资源的利用。
jdk7中的分支合并框架
fork/join的运行方式: if(任务足够小或不可再分割){ 直接顺序计算该任务 } else { 1、将任务分割成两个子任务 2、递归调用该方法拆分每个子任务,直至所有的子任务不可再分 3、合并每个子任务的结果 }
其中,还涉及到“工作窃取”算法,具体可参考:http://www.infoq.com/cn/articles/fork-join-introduction/