Java併發系列6-Fork/Join框架

一、介紹

1、Fork/Join框架是Java7提供了的一個用於並行執行任務的框架, 是一個把大任務分割成若干個小任務,最終彙總每個小任務結果後得到大任務結果的框架。

Fork:把一個大任務切分爲若干子任務並行的執行。
Join:合併這些子任務的執行結果,最後得到這個大任務的結果。

Fork/Join示意圖
上圖中,上部的Task依賴於下部的Task執行,只有當各個子任務執行完成後,才能得到Task0的返回結果。

2、原理
分割任務。需要有一個fork類來將主任務分割成子任務,存在嵌套分隔的情況。

執行任務併合並結果。分割的子任務分別放在各自的雙端隊列中,之後啓動幾個線程分別從其所有的雙端隊列中獲取任務執行。子任務執行完的結果都統一放在一個結果隊列中,啓動一個線程從此隊列中獲取併合並數據。

Fork/Join使用兩個類來完成以上兩件事情:

  • ForkJoinTask:使用ForkJoin框架,必須首先創建一個ForkJoin任務。它提供在任務中執行fork()和join()操作,通常情況下我們不需要直接繼承ForkJoinTask類,而只需要繼承它的子類,Fork/Join框架提供了以下兩個子類:
    • RecursiveAction:用於沒有返回結果的任務。
    • RecursiveTask :用於有返回結果的任務。
  • ForkJoinPool :ForkJoinTask需要通過ForkJoinPool來執行,任務分割出的子任務會添加到當前工作線程所維護的雙端隊列中,進入隊列的頭部。當一個工作線程的隊列裏暫時沒有任務時,它會隨機從其他工作線程的隊列的尾部獲取一個任務。

二、例子

通過一個例子,簡單介紹fork/join框架的使用,計算任務是:計算1 + 2 + … + 100
1、首先是繼承類,由於我們需要子任務返回結果,因此選擇帶有返回結果的RecursiveTask
2、繼承RecursiveTask類後,需要實現其父類的抽象方法compute()
3、任務分隔, 設定閾值爲10,如果超過該閾值,則進行分隔。

public class CountTask extends RecursiveTask<Integer> {

    private static final int THRESHOLD = 10; // 閾值
    private int start;
    private int end;

    public CountTask(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        boolean isNeedSplit = (end - start) > THRESHOLD;
        int sum = 0;

        if (!isNeedSplit) {
            for (int i = start; i <= end; ++i) {
                sum += i;
            }
            return sum;
        }

        // 分隔任務
        int mid = (start + end) >> 1;
        CountTask lowTask = new CountTask(start, mid);
        CountTask highTask = new CountTask(mid + 1, end);
        // 子任務執行
        lowTask.fork();
        highTask.fork();
        // 獲取子任務計算結果
        return lowTask.join() + highTask.join();
    }

    public static void main(String[] args) throws Exception {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        // 創建新任務
        CountTask task = new CountTask(1, 100);
        // 提交任務
        Future<Integer> ret = forkJoinPool.submit(task);
        // 輸出結果
        System.out.println(ret.get());
    }
}
發佈了54 篇原創文章 · 獲贊 15 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章