1. 程式人生 > >Java併發程式設計與技術內幕:ForkJoin 框架初探

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個訂單”的神器,本課程目標:徹底精通一個如此優秀的開源框架,面試秒殺面試官。本章會帶領小夥伴們先了解課程大綱與重點,然後模擬千萬,億級