什么是forkjoin?
就是将单线程下的一个大任务,拆分成多个小任务,将多个小任务派给其它线程执行,最终将所有执行的结果汇总得到最终的结果
本质是:将单线程的大任务转成多线程的小任务,所以对于大任务有效率上的提高。
例如线程1上的任务执行forkJoin后分为了四个任务,这四个任务放在双端队列中等待线程1执行。
另外一个线程2刚刚完成了其它的任务此时处于空闲状态,在forkjoin下 它会执行工作窃取,去
线程1的双端队列中,从另一个端窃取线程进行执行。
2,java中如何使用forkjoin
- 继承类 ForkJoinTask<V>的子类编写一个任务类:RecursiveAction为递归事件无返回值,或者RecursiveTask为递归任务有返回值
- 实现对应的抽象方法compute
- 将实例化的任务对象交给ForkJoinPool执行
@Test public void test11() throws ExecutionException, InterruptedException { long start = System.currentTimeMillis(); ForkJoinPool forkJoinPool = new ForkJoinPool();//建立forkjoin池 forkjoinDemo task = new forkjoinDemo(0, 10_0000_0000);//创建一个任务 ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务 long sum =submit.get();//获取任务的最终结构 long end = System.currentTimeMillis(); System.out.println("sum = "+sum+" time = "+(end-start));//395 } import java.util.concurrent.RecursiveTask; /** * 这是一个任务类 * compute方法是对任务的拆分 */ public class forkjoinDemo extends RecursiveTask<Long> { private long start; private long end; private long temp=10000L; forkjoinDemo(long start,long end) { this.start=start; this.end=end; } @Override protected Long compute() { long sum=0L; if ((end-start)<temp) { for (long i = start; i < end; i++) { sum += i; } return sum; }else { //将任务进行分解 long middle = (start+end)/2; forkjoinDemo forkjoinDemo1 = new forkjoinDemo(start, middle); forkjoinDemo forkjoinDemo2 = new forkjoinDemo(middle+1, end); forkjoinDemo1.fork();//将任务压入队列 forkjoinDemo2.fork();//将任务压入队列 return forkjoinDemo1.join()+forkjoinDemo2.join(); } } }
3,对比测试,发现还是stream流的计算速度最快
@Test public void test10() { long sum =0; long start = System.currentTimeMillis(); for (long i=0;i<=10_0000_0000;i++) { sum +=i; } long end = System.currentTimeMillis(); System.out.println("sum = "+sum+" time = "+(end-start));//445 } @Test public void test11() throws ExecutionException, InterruptedException { long start = System.currentTimeMillis(); ForkJoinPool forkJoinPool = new ForkJoinPool();//建立forkjoin池 forkjoinDemo task = new forkjoinDemo(0, 10_0000_0000);//创建一个任务 ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务 long sum =submit.get();//获取任务的最终结构 long end = System.currentTimeMillis(); System.out.println("sum = "+sum+" time = "+(end-start));//395 } @Test public void test12() { long start = System.currentTimeMillis(); long sum =LongStream.rangeClosed(0,10_0000_0000L).parallel().reduce(0,Long::sum); long end = System.currentTimeMillis(); System.out.println("sum = "+sum+" time = "+(end-start));//260 }