ForkJoinPool 是 JDK1.7 開始提供的線程池。為了解決 CPU 負載不均衡的問題。如某個較大的任務,被一個線程去執行,而其他線程處於空閑狀態。
ForkJoinTask 表示一個任務,ForkJoinTask 的子類中有 RecursiveAction 和 RecursiveTask。
RecursiveAction 無返回結果;RecursiveTask 有返回結果。
重寫 RecursiveAction 或 RecursiveTask 的 compute(),完成計算或者可以進行任務拆分。
調用 ForkJoinTask 的 fork() 的方法,可以讓其他空閑的線程執行這個 ForkJoinTask;
調用 ForkJoinTask 的 join() 的方法,將多個小任務的結果進行匯總。
無返回值打印任務拆分
package constxiong.interview; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveAction; import java.util.concurrent.TimeUnit; /** * 測試 ForkJoinPool 線程池的使用 * @author ConstXiong * @date 2019-06-12 12:05:55 */ public class TestForkJoinPool { public static void main(String[] args) throws Exception { testNoResultTask();//測試使用 ForkJoinPool 無返回值的任務執行 } /** * 測試使用 ForkJoinPool 無返回值的任務執行 * @throws Exception */ public static void testNoResultTask() throws Exception { ForkJoinPool pool = new ForkJoinPool(); pool.submit(new PrintTask(1, 200)); pool.awaitTermination(2, TimeUnit.SECONDS); pool.shutdown(); } } /** * 無返回值的打印任務 * @author ConstXiong * @date 2019-06-12 12:07:02 */ class PrintTask extends RecursiveAction { private static final long serialVersionUID = 1L; private static final int THRESHOLD = 49; private int start; private int end; public PrintTask(int start, int end) { super(); this.start = start; this.end = end; } @Override protected void compute() { //當結束值比起始值 大於 49 時,按數值區間平均拆分為兩個任務;否則直接打印該區間的值 if (end - start <THRESHOLD) { for (int i = start; i <= end; i++) { System.out.println(Thread.currentThread().getName() + ", i = " + i); } } else { int middle = (start + end) / 2; PrintTask firstTask = new PrintTask(start, middle); PrintTask secondTask = new PrintTask(middle + 1, end); firstTask.fork(); secondTask.fork(); } } }
有返回值計算任務拆分、結果合並
package constxiong.interview; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.RecursiveTask; import java.util.concurrent.TimeUnit; /** * 測試 ForkJoinPool 線程池的使用 * @author ConstXiong * @date 2019-06-12 12:05:55 */ public class TestForkJoinPool { public static void main(String[] args) throws Exception { testHasResultTask();//測試使用 ForkJoinPool 有返回值的任務執行,對結果進行合並。計算 1 到 200 的累加和 } /** * 測試使用 ForkJoinPool 有返回值的任務執行,對結果進行合並。計算 1 到 200 的累加和 * @throws Exception */ public static void testHasResultTask() throws Exception { int result1 = 0; for (int i = 1; i <= 200; i++) { result1 += i; } System.out.println("循環計算 1-200 累加值:" + result1); ForkJoinPool pool = new ForkJoinPool(); ForkJoinTask<Integer> task = pool.submit(new CalculateTask(1, 200)); int result2 = task.get(); System.out.println("並行計算 1-200 累加值:" + result2); pool.awaitTermination(2, TimeUnit.SECONDS); pool.shutdown(); } } /** * 有返回值的計算任務 * @author ConstXiong * @date 2019-06-12 12:07:25 */ class CalculateTask extends RecursiveTask<Integer> { private static final long serialVersionUID = 1L; private static final int THRESHOLD = 49; private int start; private int end; public CalculateTask(int start, int end) { super(); this.start = start; this.end = end; } @Override protected Integer compute() { //當結束值比起始值 大於 49 時,按數值區間平均拆分為兩個任務,進行兩個任務的累加值匯總;否則直接計算累加值 if (end - start <= THRESHOLD) { int result = 0; for (int i = start; i <= end; i++) { result += i; } return result; } else { int middle = (start + end) / 2; CalculateTask firstTask = new CalculateTask(start, middle); CalculateTask secondTask = new CalculateTask(middle + 1, end); firstTask.fork(); secondTask.fork(); return firstTask.join() + secondTask.join(); } } }
- Java 自學指南
- Java 面試題匯總PC端瀏覽【點這里】
- Java知識圖譜
- Java 面試題匯總小程序瀏覽,掃二維碼
所有資源資源匯總於公眾號