JAVA併發編程Fork/Join(分而治之思想)之(ForkJoinPool/ForkJoinTask)

Java提供Fork/Join框架用於並行執行任務,它的思想就是講一個大任務分割成若干小任務,最終彙總每個小任務的結果從而得到這個大任務的結果。

這裏我們也藉助這種思想來處理一個超大任務的運算,採用ForkJoinPool/ForkJoinTask這種方式。

我們來看一段ForkJoinPool/ForkJoinTask方式實現的代碼

package com.forkjoin;

import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * ForkJoinPool
 * 解決方案採用多線程拆分任務實現(Fork/join)
 *
 * @author 小輝GE/小輝哥
 * <p>
 * 2019年8月10日 下午19:30:00
 */
public class ParallelForkJoinPool {
    public static void main(String[] args) throws IOException {
        // 定義arry數組
        int[] arry = new int[10000];
        for (int i = 0; i < arry.length; i++) {
            arry[i] = (int) (Math.random() * 1000);
        }
        // 直接執行方式
        System.out.println("直接執行運算結果是:" + Arrays.stream(arry).sum());

        // Fork/join方式(ForkJoinPool產生的是精靈線程/daemon)
        ForkJoinPool fjp = new ForkJoinPool();
        AddTask task = new AddTask(0, arry.length, arry);
        fjp.execute(task);
        Long result = task.join();
        System.out.println("Fork/join執行運算結果是:" + result);
    }

    // RecursiveTask 實現方式有返回值
    // RecursiveAction 實現方式無返回值
    static class AddTask extends RecursiveTask<Long> {
        int start;
        int end;
        int middle = 500;
        int[] arry;

        AddTask(int start_, int end_, int[] arry_) {
            start = start_;
            end = end_;
            arry = arry_;
        }

        @Override
        protected Long compute() {
            if (end - start <= middle) {
                return getSum(start, end, arry);
            }
            int index = start + (end - start) / 2;
            AddTask subTask1 = new AddTask(start, index, arry);
            AddTask subTask2 = new AddTask(index, end, arry);
            subTask1.fork();
            subTask2.fork();
            return subTask1.join() + subTask2.join();
        }
    }

    /**
     * 實現begin到end求和
     *
     * @param begin
     * @param end
     * @param arry
     * @return
     */
    static Long getSum(int begin, int end, int[] arry) {
        Long sum = 0l;
        for (int i = begin; i < end; i++)
            sum += arry[i];
        return sum;
    }
}


測試輸出結果如下:

結果分析:

其實我們可以看出,兩種方式運算結果都是一致的。如果我們把運算時間打出來,也可以看出ForkJoinPool/ForkJoinTask方式執行效率也會高很多。

以上代碼僅供參考,如有不當之處,歡迎指出!!!

更多幹貨,歡迎大家關注和聯繫我。期待和大家一起更好的交流、探討技術!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章