Fork-Join并行执行任务框架应用
例子1
我们都知道,快排有2个步骤:
第1步,拿数组的第1个元素,把元素划分成2半,左边的比该元素小,右边的比该元素大;
第2步,对左右的2个子数组,分别排序。
可以看出,这里左右2个子数组,可以相互独立的,并行计算。因此可以利用ForkJoin框架, 代码如下:
//定义一个Task,基础自RecursiveAction,实现其compute方法
class SortTask extends RecursiveAction {
final long[] array;
final int lo;
final int hi;
private int THRESHOLD = 0; //For demo only
public SortTask(long[] array) {
this.array = array;
this.lo = 0;
this.hi = array.length - 1;
}
public SortTask(long[] array, int lo, int hi) {
this.array = array;
this.lo = lo;
this.hi = hi;
}
protected void compute() {
if (hi - lo < THRESHOLD)
sequentiallySort(array, lo, hi);
else {
int pivot = partition(array, lo, hi); //划分
coInvoke(new SortTask(array, lo, pivot - 1), new SortTask(array,
pivot + 1, hi)); //递归调,左右2个子数组
}
}
private int partition(long[] array, int lo, int hi) {
long x = array[hi];
int i = lo - 1;
for (int j = lo; j < hi; j++) {
if (array[j] <= x) {
i++;
swap(array, i, j);
}
}
swap(array, i + 1, hi);
return i + 1;
}
private void swap(long[] array, int i, int j) {
if (i != j) {
long temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
private void sequentiallySort(long[] array, int lo, int hi) {
Arrays.sort(array, lo, hi + 1);
}
}
//测试函数
public void testSort() throws Exception {
ForkJoinTask sort = new SortTask(array); //1个任务
ForkJoinPool fjpool = new ForkJoinPool(); //1个ForkJoinPool
fjpool.submit(sort); //提交任务
fjpool.shutdown(); //结束。ForkJoinPool内部会开多个线程,并行上面的子任务
fjpool.awaitTermination(30, TimeUnit.SECONDS);
}
例子2: 求1到n个数的和
//定义一个Task,基础自RecursiveTask,实现其commpute方法
public class SumTask extends RecursiveTask<Long>{
private static final int THRESHOLD = 10;
private long start;
private long end;
public SumTask(long n) {
this(1,n);
}
private SumTask(long start, long end) {
this.start = start;
this.end = end;
}
@Override //有返回值
protected Long compute() {
long sum = 0;
if((end - start) <= THRESHOLD){
for(long l = start; l <= end; l++){
sum += l;
}
}else{
long mid = (start + end) >>> 1;
SumTask left = new SumTask(start, mid); //分治,递归
SumTask right = new SumTask(mid + 1, end);
left.fork();
right.fork();
sum = left.join() + right.join();
}
return sum;
}
private static final long serialVersionUID = 1L;
}
//测试函数
public void testSum() throws Exception {
SumTask sum = new SumTask(100); //1个任务
ForkJoinPool fjpool = new ForkJoinPool(); //1个ForkJoinPool
Future<Long> future = fjpool.submit(sum); //提交任务
Long r = future.get(); //获取返回值
fjpool.shutdown();
}