Fork/Join 執行緒池
阿新 • • 發佈:2021-08-20
簡述
Fork/Join 是 JDK 1.7 加入的新的執行緒池實現,它體現的是一種分治思想,適用於能夠進行任務拆分的 cpu 密集型運算Fork/Join 在分治的基礎上加入了多執行緒,可以把每個任務的分解和合並交給不同的執行緒來完成,進一步提升了運算效率Fork/Join 預設會建立與 cpu 核心數大小相同的執行緒池
使用
基本的使用流程就是建立任務然後交給執行緒池執行
這裡的任務就不是runnable和callable的物件了,得用RecursiveTask或RecursiveAction的子類,前者有返回結果,後者沒有返回結果
forkjoin執行緒池的分治思想和遞迴很類似,比如我們想要求1到n的和,若n=5時,
重寫的compute方法就是該遞迴方法
package ThreadTest.ThreadPool; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveAction; import java.util.concurrent.RecursiveTask; public class TestFork { public static void main(String[] args) { ForkJoinPool poolsample= new ForkJoinPool(5); System.out.println(pool.invoke(new MyTask(5))); //f(5) = 5 + f(4) f(4) = 4 + f(3)... } } class MyTask extends RecursiveTask<Integer> { private int n; public MyTask(int n) { this.n = n; } @Override protected Integer compute() {if(n==1) return 1;//終止條件 MyTask t1 = new MyTask(n-1); t1.fork();//讓一個執行緒去執行 Integer result = n + t1.join();//獲取任務結果 return result; } }
任務拆分的優化,本來我們的任務拆分是這樣的:
可以看到執行緒的並行度很低,執行緒都要依賴下一個拆分任務的執行緒的結束才能返回
我們可以改變任務拆分的方式:
class AddTask1 extends RecursiveTask<Integer> { int n; public AddTask1(int n) { this.n = n; } @Override public String toString() { return "{" + n + '}'; } @Override protected Integer compute() { // 如果 n 已經為 1,可以求得結果了 if (n == 1) { log.debug("join() {}", n); return n; } // 將任務進行拆分(fork) AddTask1 t1 = new AddTask1(n - 1); t1.fork(); log.debug("fork() {} + {}", n, t1); // 合併(join)結果 int result = n + t1.join(); log.debug("join() {} + {} = {}", n, t1, result); return result; } }sample2
這樣用二分的思想,從中間開始拆分,呼叫鏈就是這樣了:
可以看到t3和t2是可以並行的,這樣就能提高cpu資源利用率
一點一點積累,一點一點蛻變!