場景:當任務很多,成千上萬個,或者單個任務很大,執行起來很耗時間,這時,就可以把任務進行拆分,拆分成多個小任務去執行,然后小任務執行完畢后再把每個小任務執行的結果合並起來,這樣就可以節省時間。
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中,然后就可以獲取到每一個小任務執行的結果。