ForkJoinPool的工作原理和使用


       場景:當任務很多,成千上萬個,或者單個任務很大,執行起來很耗時間,這時,就可以把任務進行拆分,拆分成多個小任務去執行,然后小任務執行完畢后再把每個小任務執行的結果合並起來,這樣就可以節省時間。

        ForkJoinPool實現了ExecutorService接口,所以它也是一種線程池,做的工作就是,把一個任務拆分成若干個小任務執行,然后再把小任務執行的結果匯總。

下面是一個小例子:

 

    //初始化一個ForkJoinPool
    static ForkJoinPool pool = new ForkJoinPool(3,
            ForkJoinPool.defaultForkJoinWorkerThreadFactory,
            null,
            true);

    //一個集合,模擬網站
    static ArrayList<String> list = new ArrayList<>();
    //集合中的數據
    static void addList() {
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
        list.add("www.baidu.com");
        list.add("www.blog.csdn.net");
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        addList();
        //提交任務
        ForkJoinTask<String> task =  pool.submit(new Work(list, 0, list.size()));
        System.out.println(task.get());


    }

    //模擬請求
    public static String doRequest(String url, int index) {
        return index + "--》請求測試:" + url + "\n";
    }

    //需要繼承RecursiveTask,來實現自己的拆分邏輯
    static class Work extends RecursiveTask<String> {
        List<String> list;
        int start;
        int end;

        public Work(List<String> list, int start, int end) {
            this.list = list;
            this.start = start;
            this.end = end;
        }

        @Override
        protected String compute() {
            int count = end - start;
            String result = "";
            //當任務小於10個時直接執行,否則就拆分
            if (count <= 10) {
                for (int i = 0; i<list.size(); i++) {
                    result += doRequest(list.get(i), i);
                }
                return result;
            } else {
                //獲取任務數量索引的中間值
                int x = (start + end) / 2;
                //拆分任務
                Work work1 = new Work(list, start, x);
                work1.fork();
                //拆分任務
                Work work2 = new Work(list, x, end);
                work2.fork();
                //獲取任務執行結果
                result += work1.join();
                result += work2.join();
                return result;
            }
        }
    }

執行邏輯:

第一步:

第二步:

 第三步:

每一個線程有任務后,都會去拆分任務,當拆分的小任務滿足執行條件后,就會去執行,然后按照層級,從拆分后最小的層級執行完任務,一層層向上回收任務結果,最后到ForkJoinTask中,然后就可以獲取到每一個小任務執行的結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM