1.什麼是Fork/join架構
用于執行并行任務,是把一個大任務分成若幹個小任務執行(fork),最終彙總每個小任務結果後得到大任務結果(join)的架構。
适用于CPU密集型運算,預設會建立與CPU核心數相等的線程池。
2.工作竊取算法
2.1 介紹
工作竊取(work-stealing)算法是指某個線程從其他隊列裡竊取任務來執行。
幹完活的線程會從其他線程的雙端隊列尾部竊取任務來完成,而被竊取的線程則是從雙端隊列的頭部取出任務。
2.2 優點
充分利用線程進行并行計算,減少了線程間的競争。
2.3 缺點
在某些情況下還是存在競争,比如雙端隊列中隻有一個任務時。并且該算法會消耗了更多的系統資源,比如建立多個線程和多個雙端隊列。
3.使用
分割的子任務分别放在雙端隊列裡,然後幾個啟動線程分别從雙端隊列裡擷取任務執行。子任務執行完的結果都統一放在一個隊列裡,啟動一個線程從隊列裡拿資料,然後合并這些資料。
①ForkJoinTask:我們要使用ForkJoin架構,必須首先建立一個ForkJoin任務。它提供在任務中執行fork()和join()操作的機制。通常情況下,我們不需要直接繼承ForkJoinTask類,隻需要繼承它的子類,Fork/Join架構提供了以下兩個子類。
-RecursiveAction:用于沒有傳回結果的任務。
-RecursiveTask:用于有傳回結果的任務。
②ForkJoinPool:ForkJoinTask需要通過ForkJoinPool來執行。
使用示例代碼如下
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
public class CountTask extends RecursiveTask<Integer> {
private static final int THRESHOLD=2;
private int start;
private int end;
public CountTask(int start,int end){
this.start=start;
this.end=end;
}
@Override
protected Integer compute() {
int sum=0;
boolean canCompute=(end-start)<=THRESHOLD;
if(canCompute){
for(int i=start;i<=end;i++){
sum+=i;
}
}
else{
int middle=(start+end)/2;
CountTask leftTask=new CountTask(start,middle);
CountTask rightTask=new CountTask(middle+1,end);
leftTask.fork();
rightTask.fork();
int leftResult=leftTask.join();
int rightResult=rightTask.join();
sum=leftResult+rightResult;
}
return sum;
}
public static void main(String[] args) {
ForkJoinPool pool=new ForkJoinPool();
CountTask task=new CountTask(2,4);
Future<Integer> result=pool.submit(task);
try{
System.out.println(result.get());
}
catch (Exception e){
}
}
}
輸出
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNyZuBnLygDNxUjNxkDM2ITMxAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)