Fork-Join多线程并发框架
——JDK7提供的一种新的并发框架:分解、合并 基于分治递归的思想
——适用于整体任务量不确定,但单个最小任务确定的情况使用
ForkJoin并发框架的主要类包括:
ForkJoinPool:ForkJoin线程池,实现了ExecutorService接口和工作窃取算法,用于线程调度与管理。
ForkJoinTask:ForkJoin任务,提供了fork()方法和join()方法。通常不直接使用,而是使用以下子类:
- RecursiveAction:无返回值的任务,通常用于只fork不join的情形
- RecursiveTask:有返回值的任务,通常用于fork+join的情形
递归任务类SumTask
——继承RecursiveTask递归父类 重写compute()计算方法
——若计算区间小于一定值 那么计算返回
——否则 递归分解成更小的任务
——调用invokeAll()方法执行 结果采用Join方法获取
——将结果相加返回
//继承 Recurisetask 递归任务父类
public class SumTask extends RecursiveTask<Long>{
private int start;
private int end;
public SumTask(int start,int end)
{
this.start=start;
this.end=end;
}
//static final变量永远不变 编译器就确定
public static final int threadhold=5;//最小任务区间长度
@Override
protected Long compute()
{
Long sum=0L;
//任务小于给定值 计算
boolean canCompute=(end-start)<=threadhold;
if(canCompute)
{
for(int i=start;i<=end;i++)
sum+=i;
}
else
{
int middle=(start+end)/2;
SumTask subTask1=new SumTask(start,middle);
SumTask subTask2=new SumTask(middle+1,end);
//递归计算
invokeAll(subTask1,subTask2);
Long sum1=subTask1.join();
Long sum2=subTask2.join();
sum=sum1+sum2;
}
return sum;
}
}
主线程
——其中forkJoinPool.submit提交任务(传入RecursiveTask对象)
——ForkJoinPool.getParallelism获取并行的线程数目
(注意 并发(Concurrency). VS 并行(Parallelism).)
——
并发:
偏重于多个任务交替执行,而多个任务之间有可能还是串行的。
并行:
真正意义上的“同时执行”。
public class SumTest {
public static void main(String[] args) throws ExecutionException,InterruptedException{
// TODO Auto-generated method stub
//创建线程池
ForkJoinPool pool=new ForkJoinPool();
//创建任务
SumTask task=new SumTask(1,100000000);
//提交任务
ForkJoinTask<Long> result=pool.submit(task);
//等待结果
do
{
System.out.printf("Main:Thread count %d \n", pool.getActiveThreadCount());
System.out.printf("Main Paralelism %d \n", pool.getParallelism());
try
{
Thread.sleep(50);
}catch(InterruptedException e)
{
e.printStackTrace();
}
}while(!task.isDone());
//输出结果
System.out.println(result.get().toString());
}
}
执行结果: