介紹一下ForkJoinPool的使用


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();
        }
    }
    
}

 


原文鏈接
 


 

所有資源資源匯總於公眾號



 

 


免責聲明!

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



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