并行流 多线程 把一个内容分成多个数据块 不同线程分别处理每个数据块的流
串行流 单线程 一个线程处理所有数据
java8 对并行流优化 StreamAPI 通过parallel() 并行流
sequential() 顺序流
注意:
使用并行流并不是一定会提高效率,因为jvm对数据进行切片和切换线程也是需要时间的。
所以数据量越小,串行操作越快;数据量越大,并行操作效果越好。
StreamAPI 通过parallel() 并行流 底层是Fork/join 框架
Fork/join 框架 将任务分解成 若干小任务(分解到不可分解为止) 小任务的结果 join汇总
Fork/Join与传统线程池的区别!
Fork/Join采用“工作窃取模式”,当执行新的任务时他可以将其拆分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随即线程中偷一个并把它加入自己的队列中。
就比如两个CPU上有不同的任务,这时候A已经执行完,B还有任务等待执行,这时候A就会将B队尾的任务偷过来,加入自己的队列中,对于传统的线程,ForkJoin更有效的利用的CPU资源!
ForkJoin的实现:实现这个框架需要继承RecursiveTask 或者 RecursiveAction ,RecursiveTask是有返回值的,相反Action则没有
1 package com.wf.zhang.java8.stream; 2 3 import java.util.concurrent.RecursiveTask; 4 5 6 public class ForkJoinCalculate extends RecursiveTask<Long> { 7 8 private static final long serialVersionUID = 13475679780L; 9 10 private long start; 11 private long end; 12 13 private static final long THRESHOLD = 10000L; //临界值 14 15 //计算从start-end之和 16 public ForkJoinCalculate(long start, long end) { 17 this.start = start; 18 this.end = end; 19 } 20 21 @Override 22 protected Long compute() { 23 long length = end - start; 24 25 if(length <= THRESHOLD){ 26 long sum = 0; 27 28 for (long i = start; i <= end; i++) { 29 sum += i; 30 } 31 return sum; 32 }else{ 33 long middle = (start + end) / 2; 34 35 ForkJoinCalculate left = new ForkJoinCalculate(start, middle); 36 left.fork(); //拆分,并将该子任务压入线程队列 37 38 ForkJoinCalculate right = new ForkJoinCalculate(middle+1, end); 39 right.fork(); 40 //汇总 41 return left.join() + right.join(); 42 } 43 44 } 45 46 }
1 package com.wf.zhang.java8.stream; 2 3 import org.junit.Test; 4 5 import java.util.concurrent.ForkJoinPool; 6 import java.util.concurrent.ForkJoinTask; 7 import java.util.stream.LongStream; 8 9 public class TestForkJoin { 10 11 @Test 12 public void test1(){ 13 long start = System.currentTimeMillis(); 14 15 ForkJoinPool pool = new ForkJoinPool(); 16 ForkJoinTask<Long> task = new ForkJoinCalculate(0L, 10000000000L); 17 18 long sum = pool.invoke(task); 19 System.out.println(sum); 20 21 long end = System.currentTimeMillis(); 22 23 System.out.println("耗费的时间为: " + (end - start)); 24 } 25 26 //java8 优化并行流 27 @Test 28 public void test3(){ 29 long start = System.currentTimeMillis(); 30 31 Long sum = LongStream.rangeClosed(0L, 10000000000L) 32 .parallel() 33 .sum(); 34 35 System.out.println(sum); 36 37 long end = System.currentTimeMillis(); 38 39 System.out.println("耗费的时间为: " + (end - start)); 40 } 41 }