Java併發程式設計與技術內幕:ForkJoin 框架初探
一、ForkJoin介紹
ForkJoin是Java7提供的原生多執行緒並行處理框架,其基本思想是將大人物分割成小任務,最後將小任務聚合起來得到結果。它非常類似於HADOOP提供的MapReduce框架,只是MapReduce的任務可以針對叢集內的所有計算節點,可以充分利用叢集的能力完成計算任務。ForkJoin更加類似於單機版的MapReduce。
二、工作竊取
工作竊取(work-stealing)演算法是指某個執行緒從其他佇列裡竊取任務來執行。
一個大任務分割為若干個互不依賴的子任務,為了減少執行緒間的競爭,把這些子任務分別放到不同的佇列裡,並未每個佇列建立一個單獨的執行緒來執行佇列裡的任務,執行緒和佇列一一對應。比如執行緒1負責處理1佇列裡的任務,2執行緒負責2佇列的。但是有的執行緒會先把自己佇列裡的任務幹完,而其他執行緒對應的佇列裡還有任務待處理。幹完活的執行緒與其等著,不如幫其他執行緒幹活,於是它就去其他執行緒的佇列裡竊取一個任務來執行。而在這時它們可能會訪問同一個佇列,所以為了減少竊取任務執行緒和被竊取任務執行緒之間的競爭,通常會使用雙端佇列,被竊取任務執行緒永遠從雙端佇列的頭部拿任務執行,而竊取任務執行緒永遠從雙端佇列的尾部拿任務執行。
三、使用介紹
Java提供了ForkJoinPool來支援將一個任務拆分成多個“小任務”平行計算,再把多個“小任務”的結果合成總的計算結果。
第一步分割任務。首先我們需要有一個fork類來把大任務分割成子任務,有可能子任務還是很大,所以還需要不停的分割,直到分割出的子任務足夠小。
第二步執行任務併合並結果。分割的子任務分別放在雙端佇列裡,然後幾個啟動執行緒分別從雙端佇列裡獲取任務執行。子任務執行完的結果都統一放在一個佇列裡,啟動一個執行緒從佇列裡拿資料,然後合併這些資料。
Fork/Join使用兩個類來完成以上兩件事情:
-
ForkJoinTask:我們要使用ForkJoin框架,必須首先建立一個ForkJoin任務。它提供在任務中執行fork()和join()操作的機制,通常情況下我們不需要直接繼承ForkJoinTask類,而只需要繼承它的子類,Fork/Join框架提供了以下兩個子類:
-
-
RecursiveAction:用於沒有返回結果的任務。
-
RecursiveTask :用於有返回結果的任務。
-
-
ForkJoinPool :ForkJoinTask需要通過ForkJoinPool來執行,任務分割出的子任務會新增到當前工作執行緒所維護的雙端佇列中,進入佇列的頭部。當一個工作執行緒的佇列裡暫時沒有任務時,它會隨機從其他工作執行緒的佇列的尾部獲取一個任務。
例項1使用recursiveTask
public class CountTask extends RecursiveTask<Integer> { private static final long serialVersionUID = -3611254198265061729L; public static final int threshold = 2; private int start; private int end; public CountTask(int start, int end) { this.start = start; this.end = end; } @Override protected Integer compute() { int sum = 0; //如果任務足夠小就計算任務 boolean canCompute = (end - start) <= threshold; if (canCompute) { for (int i = start; i <= end; i++) { sum += i; } } else { // 如果任務大於閾值,就分裂成兩個子任務計算 int middle = (start + end) / 2; CountTask leftTask = new CountTask(start, middle); CountTask rightTask = new CountTask(middle + 1, end); // 執行子任務 leftTask.fork(); rightTask.fork(); //等待任務執行結束合併其結果 int leftResult = leftTask.join(); int rightResult = rightTask.join(); //合併子任務 sum = leftResult + rightResult; } return sum; } public static void main(String[] args) { ForkJoinPool forkjoinPool = new ForkJoinPool(); //生成一個計算任務,計算1+2+3+4 CountTask task = new CountTask(1, 100); //執行一個任務 Future<Integer> result = forkjoinPool.submit(task); try { System.out.println(result.get()); } catch (Exception e) { System.out.println(e); } } }
例項2使用recursiveAction
public class ForkJoinPoolTest {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 建立包含Runtime.getRuntime().availableProcessors()返回值作為個數的並行執行緒的ForkJoinPool
ForkJoinPool forkJoinPool = new ForkJoinPool();
// 提交可分解的PrintTask任務
forkJoinPool.submit(new PrintTask(0, 200));
forkJoinPool.awaitTermination(2, TimeUnit.SECONDS);//阻塞當前執行緒直到 ForkJoinPool 中所有的任務都執行結束
// 關閉執行緒池
forkJoinPool.shutdown();
}
}
//RecursiveAction為ForkJoinTask的抽象子類,沒有返回值的任務
class PrintTask extends RecursiveAction {
// 每個"小任務"最多隻列印50個數
private static final int MAX = 50;
private int start;
private int end;
PrintTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected void compute() {
// 當end-start的值小於MAX時候,開始列印
if ((end - start) < MAX) {
for (int i = start; i < end; i++) {
System.out.println(Thread.currentThread().getName() + " value i:"
+ i);
}
} else {
// 將大任務分解成兩個小任務
int middle = (start + end) / 2;
PrintTask left = new PrintTask(start, middle);
PrintTask right = new PrintTask(middle, end);
// 並行執行兩個小任務
left.fork();
right.fork();
}
}
}
相關推薦
Java併發程式設計與技術內幕:ForkJoin 框架初探
一、ForkJoin介紹 ForkJoin是Java7提供的原生多執行緒並行處理框架,其基本思想是將大人物分割成小任務,最後將小任務聚合起來得到結果。它非常類似於HADOOP提供的MapReduce框架,只是MapReduce的任務可以針對叢集內的所有計算節點,
Java併發程式設計與技術內幕:Callable、Future、FutureTask、CompletionService
在上一文章中,筆者介紹了執行緒池及其內部的原理。今天主要講的也是和執行緒相關的內容。一般情況下,使用Runnable介面、Thread實現的執行緒我們都是無法返回結果的。但是如果對一些場合需要執行緒返回的結果。就要使用用Callable、Future、Fut
Java併發程式設計與技術內幕:ConcurrentHashMap原始碼解析
摘要:本文主要講了Java中ConcurrentHashMap 的原始碼 ConcurrentHashMap 是java併發包中非常有用的一個類,在高併發場景用得非常多,它是執行緒安全的。要注意到雖然HashTable雖然也是執行緒安全的,但是它的效
Java併發程式設計與技術內幕:聊聊鎖的技術內幕(中)
摘要:本文主要講了讀寫鎖。 一、讀寫鎖ReadWriteLock 在上文中回顧了併發包中的可重入鎖ReentrantLock,並且也分析了它的原始碼。從中我們知道它是一個單一鎖(筆者自創概念),意思是在多人讀、多人寫、或同時有人讀和寫時。只能有一個人能拿到鎖,執行
Java併發程式設計與技術內幕:ThreadFactory、ThreadLocal
摘要:本文主要講了ThreadFactory、ThreadLocal的例項和原始碼解析一、ThreadFactory1.1 原始碼解讀ThreadFactory這個故名思義,就是一個執行緒工廠。用來建立執行緒。這裡為什麼要使用執行緒工廠呢?其實就是為了統一在建立
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰(資源同步)
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰(無密連結)
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大
Java併發程式設計(3):執行緒掛起、恢復與終止的正確方法(含程式碼)
JAVA大資料中高階架構 2018-11-06 14:24:56掛起和恢復執行緒Thread 的API中包含兩個被淘汰的方法,它們用於臨時掛起和重啟某個執行緒,這些方法已經被淘汰,因為它們是不安全的,不穩定的。如果在不合適的時候掛起執行緒(比如,鎖定共享資源時),此時便可能會發生死鎖條件——其他執行緒在等待該
Java併發程式設計(4):守護執行緒與執行緒阻塞的四種情況
守護執行緒Java中有兩類執行緒:User Thread(使用者執行緒)、Daemon Thread(守護執行緒) 使用者執行緒即執行在前臺的執行緒,而守護執行緒是執行在後臺的執行緒。 守護執行緒作用是為其他前臺執行緒的執行提供便利服務,而且僅在普通、非守護執行緒仍然執行時才需要,比如垃圾回收執行緒就是一個
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰 第1章 課程介紹 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後
某課最新Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級
某課最全Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級
2018最新Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰(已完結)
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級資料進行壓力測試。讓大
某課無加密Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰(雲盤分享)
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級
某網Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰(雲盤下載)
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰無加密
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰無加密分享
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰目前同步
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級
Java併發程式設計高階技術-高效能併發框架原始碼解析與實戰最新無加密
第1章 課程介紹(Java併發程式設計進階課程) 什麼是Disruptor?它一個高效能的非同步處理框架,號稱“單執行緒每秒可處理600W個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級