并行计算
- 并行模式
– 主从模式(Master-Slave)
– Worker模式(Worker-Worker) - Java并发编程
– Thread/Runnable/Thread组管理
– Executor
– Fork-Join框架
Fork-Join(1)
- Java7 提供另一种并行框架:分解、治理、合并(分治编程)
- 适用于整体任务量不好确定的场合(最小任务可以确定),但是可以逐层逐层分解的
比如:我们求一个数组的和,而我们不知道这个数组的长度,我们可以使用二分法将这个数组拆成两个,如果容量还是大,就使用二分法不断的拆,直到拆到合理的长度,每个线程计算一小段,然后所有的全部累加起来 - Fork-Join关键类
– ForkJoinPool 任务池
– RecursiveAction 定义具体的任务
– RecursiveTask 定义具体的任务
使用Fork-Join求数组中的和例子:
package com.torey;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.RecursiveTask;
/**
* @ClassName:SumTask
* @Description:
* @author: Torey
*/
public class SumTask extends RecursiveTask<Long> {
private int start;
private int end;
public SumTask(int start, int end) {
this.start = start;
this.end = end;
}
public static final int threadhold=5;
@Override
protected Long compute() {
Long sum=0L;
//如果任务足够小,就直接执行
//(end-start)<=threadhold 如果结束与开始不超过5个的话
//这里会不断的分解 17570303157
boolean canCompute= (end-start)<=threadhold;
if (canCompute) {
for (int i = start; i <=end; i++) {
sum=sum+i;
}
}else {
//任务大于阀值,分裂为2个任务
int middle= (start+end)/2;
SumTask sumTask1 = new SumTask(start, middle);
SumTask sumTask2 = new SumTask(middle+1, end);
//将两个任务提交
invokeAll(sumTask1,sumTask2);
//sumTask1.join()就是等待sumTask1任务结束
Long sum1 = sumTask1.join();
sumTask2.join()就是等待sumTask2任务结束
Long sum2 = sumTask2.join();
sum=sum1+sum2;
}
return sum;
}
}
package com.torey;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
/**
* @ClassName:SumTest
* @Description:
* @author: Torey
*/
public class SumTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建线程池
ForkJoinPool forkJoinPool = new ForkJoinPool();
//创建任务
SumTask task = new SumTask(1, 1000000);
//提交任务
ForkJoinTask<Long> submit = forkJoinPool.submit(task);
//等待结果
do{
System.out.printf("Main: Thread Count: %d\n",forkJoinPool.getActiveThreadCount());
System.out.printf("Main: Paralelism: %d\n",forkJoinPool.getParallelism());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while (!task.isDone());
//task.isDone() 判断线程池中的线程是否都结束了
System.out.println(submit.get().toString());
}
}
程序运行结果如下: