一、Fork Join
分而治之的辦法
JDk爲Fork/Join框架提供了很好的支持,我們想要用這個算法首先得創建一個Fork/Join任務,在JDK中這個任務就叫做:ForJoinTask,只要繼承這個類就可以創建一個任務類,但是實際使用中並不是直接繼承ForkJoinTask類,而是繼承它的子類,它有兩個子類,分別是RecursiveAction和RecursiveTask,它們之間的區別是是否返回任務結果,前者用於沒有返回結果的任務,後者用於有返回結果的任務。
ForkJoinPool
RecursiveTask
RecursiveAction
二、RecursiveTask使用
ForkJoinPoolTest:
1 package com.cy.java8; 2 3 import java.util.concurrent.ForkJoinPool; 4 import com.cy.java8.AccumulatorRecursiveAction.AccumulatorHelper; 5 6 public class ForkJoinPoolTest { 7 8 private static int[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 9 10 public static void main(String[] args) { 11 System.out.println("result = " + calc()); 12 13 AccumulatorRecursiveTask task = new AccumulatorRecursiveTask(0, data.length - 1, data); 14 ForkJoinPool forkJoinPool = new ForkJoinPool(); 15 Integer result = forkJoinPool.invoke(task); //同步調用 16 System.out.println("AccumulatorRecursiveTask result = " + result); 17 18 AccumulatorRecursiveAction action = new AccumulatorRecursiveAction(0, data.length - 1, data); 19 forkJoinPool.invoke(action); 20 System.out.println("AccumulatorRecursiveAction result = " + AccumulatorHelper.getResult()); 21 AccumulatorHelper.reset(); 22 } 23 24 /** 25 * 普通方法計算data的和 26 */ 27 private static int calc() { 28 int result = 0; 29 for (int i = 0; i < data.length; i++) { 30 result += data[i]; 31 } 32 return result; 33 } 34 }
AccumulatorRecursiveTask
1 package com.cy.java8; 2 3 import java.util.concurrent.RecursiveTask; 4 5 /** 6 * 繼承RecursiveTask,用於與結果返回的任務 7 */ 8 public class AccumulatorRecursiveTask extends RecursiveTask<Integer> { 9 10 //累加的起始下標值 11 private final int start; 12 private final int end; 13 private final int[] data; 14 15 //閾值爲3,當小於等於這個值的時候進行計算 16 private final int LIMIT = 3; 17 18 public AccumulatorRecursiveTask(int start, int end, int[] data) { 19 this.start = start; 20 this.end = end; 21 this.data = data; 22 } 23 24 @Override 25 protected Integer compute() { 26 if (end - start < LIMIT) { 27 int result = 0; 28 for (int i = start; i <= end; i++) { 29 result += data[i]; 30 } 31 return result; 32 } 33 34 int mid = (start + end) / 2; 35 36 //分爲兩個任務 37 AccumulatorRecursiveTask left = new AccumulatorRecursiveTask(start, mid, data); 38 AccumulatorRecursiveTask right = new AccumulatorRecursiveTask(mid + 1, end, data); 39 /* 40 //執行子任務 41 left.fork(); 42 right.fork(); 43 //等待子任務完成 44 Integer leftResult = left.join(); 45 Integer rightResult = right.join(); 46 //合併子任務 47 return rightResult + leftResult; 48 */ 49 50 //提交任務 51 invokeAll(left, right); 52 return left.join() + right.join(); 53 } 54 }
三、RecursiveAction使用
1 package com.cy.java8; 2 3 import java.util.concurrent.RecursiveAction; 4 import java.util.concurrent.atomic.AtomicInteger; 5 6 public class AccumulatorRecursiveAction extends RecursiveAction { 7 private int start; 8 private int end; 9 private int[] data; 10 private final int LIMIT = 3; 11 12 public AccumulatorRecursiveAction(int start, int end, int[] data) { 13 this.start = start; 14 this.end = end; 15 this.data = data; 16 } 17 18 @Override 19 protected void compute() { 20 if (end - start < LIMIT) { 21 for (int i = start; i <= end; i++) { 22 AccumulatorHelper.accumulate(data[i]); 23 } 24 } else { 25 int mid = (start + end) / 2; 26 AccumulatorRecursiveAction left = new AccumulatorRecursiveAction(start, mid, data); 27 AccumulatorRecursiveAction right = new AccumulatorRecursiveAction(mid + 1, end, data); 28 /*left.fork(); 29 right.fork(); 30 left.join(); 31 right.join();*/ 32 invokeAll(left, right); 33 } 34 } 35 36 static class AccumulatorHelper{ 37 private static final AtomicInteger result = new AtomicInteger(0); 38 39 private static void accumulate(int value){ 40 result.getAndAdd(value); 41 } 42 43 public static int getResult(){ 44 return result.get(); 45 } 46 47 public static void reset(){ 48 result.set(0); 49 } 50 } 51 }
ForkJoinPoolTest的執行結果:
result = 55 AccumulatorRecursiveTask result = 55 AccumulatorRecursiveAction result = 55
注:
1、RecursiveAction 提供的方法 invokeAll()。它表示:啓動所有的任務,並在所有任務都正常結束後返回。如果其中一個任務出現異常,則其它所有的任務都取消。invokeAll() 的參數還可以是任務的數組。
-----------