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方式执行效率也会高很多。
以上代码仅供参考,如有不当之处,欢迎指出!!!
更多干货,欢迎大家关注和联系我。期待和大家一起更好的交流、探讨技术!!!