Forkjoin是JDK1.7提供的多線程併發處理框架,本質上是對線程池的一種補充;
-
它的核心思想就是將一個大型任務拆分成很多個小任務,分別執行,最後再將小任務的結果進行彙總
-
本質就是:一個線程任務拆分成多個線程併發執行
-
工作竊取:A、B兩個線程同時執行,A的任務比較多,B先執行完了,此時B將A的一部分拿過來,替A執行,從而提升效率;
-
Forkjoin框架的使用需要用到兩個類:
ForkjoinTask:任務
ForkjoinPool:線程池
ForkjoinTask拆分任務,ForkjoinPool提供線程對象來執行任務,之後合併 -
ForkjoinTask使用的是遞歸的思想
例子:計算0-20億的和;
(1)普通方法:
public static void main(String[] args) {
Long sum=0L;
Long startTime=System.currentTimeMillis();
for(Long i=0L;i<=20_0000_0000L;i++){
sum+=i;
}
Long endTime=System.currentTimeMillis();
System.out.println(sum);
System.out.println("花費時長:"+(endTime-startTime));
}
結果爲:
(2)使用Forkjoin框架:
/*使用ForkJoin框架需要繼承RecursiveTask<Long>接口*/
public class ForkJoinTest2 extends RecursiveTask<Long> {
private Long start;
private Long end;
private Long temp=100_0000L;//臨界值
public ForkJoinTest2(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if((end-start)<temp){//如果(end-start)<temp,達到臨界值,則不能再拆分了
Long sum=0L;
for(Long i=start;i<=end;i++){
sum+=i;
}
return sum;
}else{
/*拆分的過程*/
Long avg=(start+end)/2;
ForkJoinTest2 task1=new ForkJoinTest2(start,avg);
task1.fork();//遞 就又去執行comput()方法了
ForkJoinTest2 task2=new ForkJoinTest2(avg+1,end);
task2.fork();//遞
return task1.join()+task2.join();//歸
}
}
}
public static void main(String[] args) {
Long startTime=System.currentTimeMillis();
ForkJoinPool forkJoinPool=new ForkJoinPool();//池
ForkJoinTask<Long> task=new ForkJoinTest2(0L,20_0000_0000L);//總的大任務
forkJoinPool.execute(task);//執行
Long sum=0L;
try {
sum=task.get();//get()方法獲取返回值,結果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Long endTime=System.currentTimeMillis();
System.out.println(sum);
System.out.println("耗時:"+(endTime-startTime));
}
結果爲:
可以看出,使用Forkjoin框架後,幹同樣一件事情,花費的時間會少一些