Java提供Fork/Join框架用於並行執行任務,它的思想就是講一個大任務分割成若干小任務,最終彙總每個小任務的結果從而得到這個大任務的結果。
這裏我們也藉助這種思想來處理一個超大任務的運算,採用ForkJoinPool/ForkJoinTask這種方式。
我們來看一段ForkJoinPool/ForkJoinTask方式實現的代碼
package com.forkjoin;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
/**
* ForkJoinPool
* 解決方案採用多線程拆分任務實現(Fork/join)
*
* @author 小輝GE/小輝哥
* <p>
* 2019年8月10日 下午19:30:00
*/
public class ParallelForkJoinPool {
public static void main(String[] args) throws IOException {
// 定義arry數組
int[] arry = new int[10000];
for (int i = 0; i < arry.length; i++) {
arry[i] = (int) (Math.random() * 1000);
}
// 直接執行方式
System.out.println("直接執行運算結果是:" + Arrays.stream(arry).sum());
// Fork/join方式(ForkJoinPool產生的是精靈線程/daemon)
ForkJoinPool fjp = new ForkJoinPool();
AddTask task = new AddTask(0, arry.length, arry);
fjp.execute(task);
Long result = task.join();
System.out.println("Fork/join執行運算結果是:" + result);
}
// RecursiveTask 實現方式有返回值
// RecursiveAction 實現方式無返回值
static class AddTask extends RecursiveTask<Long> {
int start;
int end;
int middle = 500;
int[] arry;
AddTask(int start_, int end_, int[] arry_) {
start = start_;
end = end_;
arry = arry_;
}
@Override
protected Long compute() {
if (end - start <= middle) {
return getSum(start, end, arry);
}
int index = start + (end - start) / 2;
AddTask subTask1 = new AddTask(start, index, arry);
AddTask subTask2 = new AddTask(index, end, arry);
subTask1.fork();
subTask2.fork();
return subTask1.join() + subTask2.join();
}
}
/**
* 實現begin到end求和
*
* @param begin
* @param end
* @param arry
* @return
*/
static Long getSum(int begin, int end, int[] arry) {
Long sum = 0l;
for (int i = begin; i < end; i++)
sum += arry[i];
return sum;
}
}
測試輸出結果如下:
結果分析:
其實我們可以看出,兩種方式運算結果都是一致的。如果我們把運算時間打出來,也可以看出ForkJoinPool/ForkJoinTask方式執行效率也會高很多。
以上代碼僅供參考,如有不當之處,歡迎指出!!!
更多幹貨,歡迎大家關注和聯繫我。期待和大家一起更好的交流、探討技術!!!