1. 拆分線程池的使用場景是什麼?java
答: 是對一組連續的數據進行耗時操做,例如 一個 大小爲 1000萬 的集合 進行操做。json
例子: 對1000萬個數據進行排序,那麼會將這個任務分割成兩個500萬的排序任務和一個針對這兩組500萬數據的合併任務。以此類推,對於500萬的數據也會作出一樣的分割處理,到最後會設置一個閾值來規定當數據規模到多少時,中止這樣的分割處理。好比,當元素的數量小於10時,會中止分割,轉而使用插入排序對它們進行排序。數組
2. 如何使用 ForkJoinPool?
答: (1)客戶端中使用:構建一個任務,將任務推到 線程池中 ide
(2)構建任務:this
2.1 三變量google
數組數據spa
begin; //數組數據中開始下標線程
end //數組數據中結束3d
2.2 compare中 執行,拆分任務(關鍵是拆分數據),合併code
例子(該代碼未運行):
public class RecursiveActionTest extends RecursiveTask<Integer> { private static final long serialVersionUID = -3611254198265061729L; //閥值(是數組的大小/線程數算出來的) public final int threshold = 0; //這兒應該有一個數組 private int[] bigNum={1,2,3,.....1000000000000}; private int start; private int end; private int threadNum=1; public RecursiveActionTest(int start, int end) { this.start = start; this.end = end; } //設置線程數並設置閥值 public void init(int threadNum){ this.threadNum=threadNum; threshold = end/threadNum; } //compute 是一個遞歸任務 @Override protected Integer compute() { int sum = 0; //若是任務足夠小就計算任務 boolean canCompute = (end - start) <= threshold; if (canCompute) { //執行加法任務(任務爲 對 數組 start位的數據到end位,求和) for (int i = start; i <= end; i++) { // 每一個任務爲:sum+i sum += bigNum[i]; } } else { // 若是任務大於閾值,就分裂成10子任務計算,step:每一份的任務數 int step = (start + end) /threadNum ; ArrayList<RecursiveActionTest> subTaskList = new ArrayList<RecursiveActionTest>(); int pos = start; //設置每一個小任務的始起始值和終止值 for (int i = 0; i < threadNum; i++) { int lastOne = pos + step; if (lastOne > end) lastOne = end; //pos和 lostOne其實對應數組中下標 RecursiveActionTest subTask = new RecursiveActionTest(pos, lastOne); pos += step + 1; subTaskList.add(subTask); //把子任務推向線程池 subTask.fork(); } // 等待全部子任務完成,並計算值 for (RecursiveActionTest task : subTaskList) { sum += task.join(); } } return sum; } public static void main(String[] args) { ForkJoinPool forkjoinPool = new ForkJoinPool(); //生成一個計算任務,計算1+2+3+4 RecursiveActionTest task = new RecursiveActionTest(1, 1000000000000); //執行一個任務 Future<Integer> result = forkjoinPool.submit(task); try { System.out.println(result.get()); } catch (Exception e) { System.out.println(e); } } }
3. 用 forkJoinPool 將 100 萬個 User對象 放進一個 JsonArray,用個人電腦雙核 用時 5.6 S,用單線程,一個For循環,用時 6.6 S
@Test public void test2(){ JsonArray jsonArray= new JsonArray(); long start = System.currentTimeMillis(); System.out.println(start); for (int i = 0; i <1000000 ; i++) { User user = new User(); user.setId(i); user.setAge("232"+i); user.setName("張三"); JsonObject jObj=new JsonObject(); jObj.addProperty("id", i); jObj.addProperty("age", 20); jObj.addProperty("name", "張三"); jsonArray.add(jObj); } long middel = System.currentTimeMillis(); //將 JsonArray中數據轉換成集合 List<User> users = JsonUtils.jsonToList(jsonArray.toString(), User.class); long end = System.currentTimeMillis(); System.out.println("將對象一個一個轉換成JsonArray:"+(middel-start)); System.out.println("JsonArray轉換成List"+(end-middel)); }
package com.xuecheng.manage_cms; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import java.util.ArrayList; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.Future; import java.util.concurrent.RecursiveTask; public class ForkJoinListTest extends RecursiveTask<JsonArray> { private static final long serialVersionUID = -3611254198265061729L; //閥值 public static int threshold=0 ; private int start; private int end; //線程數 private int threadNum = 4; public ForkJoinListTest(int start, int end) { this.start = start; this.end = end; } /** * 初始化閥值 只在主線程中調用 */ public void init(){ threshold = end/threadNum; } @Override protected JsonArray compute() { JsonArray bigJsonArray= new JsonArray(); //若是任務足夠小就計算任務 boolean canCompute = (end - start) <= threshold; if (canCompute) { //執行加法任務 // JsonArray jsonArray= new JsonArray(); for (int i = start; i <= end; i++) { User user = new User(); user.setId(i); user.setAge("232"+i); user.setName("張三"); JsonObject jObj=new JsonObject(); jObj.addProperty("id", i); jObj.addProperty("age", 20); jObj.addProperty("name", "張三"); bigJsonArray.add(jObj); } } else { // 若是任務大於閾值,就分裂成10子任務計算,step:每一份的任務數 int step = (start + end) / threadNum; ArrayList<ForkJoinListTest> subTaskList = new ArrayList<ForkJoinListTest>(); int pos = start; //設置每一個小任務的始起始值和終止值 for (int i = 0; i < threadNum; i++) { int lastOne = pos + step; if (lastOne > end) lastOne = end; ForkJoinListTest subTask = new ForkJoinListTest(pos, lastOne); pos += step + 1; subTaskList.add(subTask); //把子任務推向線程池 subTask.fork(); } // 等待全部子任務完成,並計算值 for (ForkJoinListTest task : subTaskList) { bigJsonArray.addAll(task.join()); } } return bigJsonArray; } public static void main(String[] args) { ForkJoinPool forkjoinPool = new ForkJoinPool(); //生成一個計算任務,計算1+2+3+4 ForkJoinListTest task = new ForkJoinListTest(1, 1000000); //須要初始化閥值 task.init(); long begain = System.currentTimeMillis(); //執行一個任務 Future<JsonArray> result = forkjoinPool.submit(task); try { JsonArray jsonElements = result.get(); long end = System.currentTimeMillis(); // System.out.println(jsonElements); System.out.println("耗時:"+(end-begain)); } catch (Exception e) { System.out.println(e); } } }