日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java并發中的Fork/Join 框架機制詳解

瀏覽:48日期:2022-08-08 17:21:52
什么是 Fork/Join 框架

Fork/Join 框架是一種在 JDk 7 引入的線程池,用于并行執行把一個大任務拆成多個小任務并行執行,最終匯總每個小任務結果得到大任務結果的特殊任務。通過其命名也很容易看出框架主要分為 Fork 和 Join 兩個階段,第一階段 Fork 是把一個大任務拆分為多個子任務并行的執行,第二階段 Join 是合并這些子任務的所有執行結果,最后得到大任務的結果。

這里不難發現其執行主要流程:首先判斷一個任務是否足夠小,如果任務足夠小,則直接計算,否則,就拆分成幾個更小的小任務分別計算,這個過程可以反復的拆分成一系列小任務。Fork/Join 框架是一種基于 分治 的算法,通過拆分大任務成多個獨立的小任務,然后并行執行這些小任務,最后合并小任務的結果得到大任務的最終結果,通過并行計算以提高效率。。

Fork/Join 框架使用示例

下面通過一個計算列表中所有元素的總和的示例來看看 Fork/Join 框架是如何使用的,總的思路是:將這個列表分成許多子列表,然后對每個子列表的元素進行求和,然后,我們再計算所有這些值的總和就得到原始列表的和了。Fork/Join 框架中定義了 ForkJoinTask 來表示一個 Fork/Join 任務,其提供了 fork()、join() 等操作,通常情況下,我們并不需要直接繼承這個 ForkJoinTask 類,而是使用框架提供的兩個 ForkJoinTask 的子類:

RecursiveAction 用于表示沒有返回結果的 Fork/Join 任務。 RecursiveTask 用于表示有返回結果的 Fork/Join 任務。

很顯然,在這個示例中是需要返回結果的,可以定義 SumAction 類繼承自 RecursiveTask,代碼入下:

/** * @author mghio * @since 2021-07-25 */public class SumTask extends RecursiveTask<Long> { private static final int SEQUENTIAL_THRESHOLD = 50; private final List<Long> data; public SumTask(List<Long> data) { this.data = data; } @Override protected Long compute() { if (data.size() <= SEQUENTIAL_THRESHOLD) { long sum = computeSumDirectly(); System.out.format('Sum of %s: %dn', data.toString(), sum); return sum; } else { int mid = data.size() / 2; SumTask firstSubtask = new SumTask(data.subList(0, mid)); SumTask secondSubtask = new SumTask(data.subList(mid, data.size())); // 執行子任務 firstSubtask.fork(); secondSubtask.fork(); // 等待子任務執行完成,并獲取結果 long firstSubTaskResult = firstSubtask.join(); long secondSubTaskResult = secondSubtask.join(); return firstSubTaskResult + secondSubTaskResult; } } private long computeSumDirectly() { long sum = 0; for (Long l : data) { sum += l; } return sum; } public static void main(String[] args) { Random random = new Random(); List<Long> data = random.longs(1_000, 1, 100).boxed().collect(Collectors.toList()); ForkJoinPool pool = new ForkJoinPool(); SumTask task = new SumTask(data); pool.invoke(task); System.out.println('Sum: ' + pool.invoke(task)); }}

這里當列表大小小于 SEQUENTIAL_THRESHOLD 變量的值(閾值)時視為小任務,直接計算求和列表元素結果,否則再次拆分為小任務,運行結果如下:

Java并發中的Fork/Join 框架機制詳解

通過這個示例代碼可以發現,Fork/Join 框架 中 ForkJoinTask 任務與平常的一般任務的主要不同點在于:ForkJoinTask 需要實現抽象方法 compute() 來定義計算邏輯,在這個方法里一般通用的實現模板是,首先先判斷當前任務是否是小任務,如果是,就執行執行任務,如果不是小任務,則再次拆分為兩個子任務,然后當每個子任務調用 fork() 方法時,會再次進入到 compute() 方法中,檢查當前任務是否需要再拆分為子任務,如果已經是小任務,則執行當前任務并返回結果,否則繼續分割,最后調用 join() 方法等待所有子任務執行完成并獲得執行結果。偽代碼如下:

if (problem is small) { directly solve problem.} else { Step 1. split problem into independent parts. Step 2. fork new subtasks to solve each part. Step 3. join all subtasks. Step 4. compose result from subresults.}Fork/Join 框架設計

Fork/Join 框架核心思想是把一個大任務拆分成若干個小任務,然后匯總每個小任務的結果最終得到大任務的結果,如果讓你設計一個這樣的框架,你會如何實現呢?(建議思考一下),Fork/Join 框架的整個流程正如其名所示,分為兩個步驟:

大任務分割 需要有這么一個的類,用來將大任務拆分為子任務,可能一次拆分后的子任務還是比較大,需要多次拆分,直到拆分出來的子任務符合我們定義的小任務才結束。 執行任務并合并任務結果 第一步拆分出來的子任務分別存放在一個個 雙端隊列 里面(P.S. 這里為什么要使用雙端隊列請看下文),然后每個隊列啟動一個線程從隊列中獲取任務執行。這些子任務的執行結果都會放到一個統一的隊列中,然后再啟動一個線程從這個隊列中拿數據,最后合并這些數據返回。

Fork/Join 框架使用了如下兩個類來完成以上兩個步驟:

ForkJoinTask 類 在上文的實例中也有提到,表示 ForkJoin 任務,在使用框架時首先必須先定義任務,通常只需要繼承自 ForkJoinTask 類的子類 RecursiveAction(無返回結果) 或者 RecursiveTask(有返回結果)即可。 ForkJoinPool 從名字也可以猜到一二了,就是用來執行 ForkJoinTask 的線程池。大任務拆分出的子任務會添加到當前線程的雙端隊列的頭部。

喜歡思考的你,心中想必會想到這么一種場景,當我們需要完成一個大任務時,會先把這個大任務拆分為多個獨立的子任務,這些子任務會放到獨立的隊列中,并為每個隊列都創建一個單獨的線程去執行隊列里的任務,即這里線程和隊列時一對一的關系,那么當有的線程可能會先把自己隊列的任務執行完成了,而有的線程則沒有執行完成,這就導致一些先執行完任務的線程干等了,這是個好問題。

既然是做并發的,肯定要最大程度壓榨計算機的性能,對于這種場景并發大師 Doug Lea 使用了工作竊取算法處理,使用工作竊取算法后,先完成自己隊列中任務的線程會去其它線程的隊列中”竊取“一個任務來執行,哈哈,一方有難,八方支援。但是此時這個線程和隊列的持有線程會同時訪問同一個隊列,所以為了減少竊取任務的線程和被竊取任務的線程之間的競爭,ForkJoin 選擇了雙端隊列這種數據結構,這樣就可以按照這種規則執行任務了:被竊取任務的線程始終從隊列頭部獲取任務并執行,竊取任務的線程使用從隊列尾部獲取任務執行。這個算法在絕大部分情況下都可以充分利用多線程進行并行計算,但是在雙端隊列里只有一個任務等極端情況下還是會存在一定程度的競爭。

Java并發中的Fork/Join 框架機制詳解

Fork/Join 框架實現原理

Fork/Join 框架的實現核心是 ForkJoinPool 類,該類的重要組成部分為 ForkJoinTask 數組和 ForkJoinWorkerThread 數組,其中 ForkJoinTask 數組用來存放框架使用者給提交給 ForkJoinPool 的任務,ForkJoinWorkerThread 數組則負責執行這些任務。任務有如下四種狀態:

NORMAL 已完成

CANCELLED 被取消

SIGNAL 信號

EXCEPTIONAL 發生異常

下面來看看這兩個類的核心方法實現原理,首先來看 ForkJoinTask 的 fork() 方法,源碼如下:

Java并發中的Fork/Join 框架機制詳解

方法對于 ForkJoinWorkerThread 類型的線程,首先會調用 ForkJoinWorkerThread 的 workQueue 的 push() 方法異步的去執行這個任務,然后馬上返回結果。繼續跟進 ForkJoinPool 的 push() 方法,源碼如下:

Java并發中的Fork/Join 框架機制詳解

方法將當前任務添加到 ForkJoinTask 任務隊列數組中,然后再調用 ForkJoinPool 的 signalWork 方法創建或者喚醒一個工作線程來執行該任務。然后再來看看 ForkJoinTask 的 join() 方法,方法源碼如下:

Java并發中的Fork/Join 框架機制詳解

Java并發中的Fork/Join 框架機制詳解

方法首先調用了 doJoin() 方法,該方法返回當前任務的狀態,根據返回的任務狀態做不同的處理:

已完成狀態則直接返回結果 被取消狀態則直接拋出異常(CancellationException) 發生異常狀態則直接拋出對應的異常

繼續跟進 doJoin() 方法,方法源碼如下:

Java并發中的Fork/Join 框架機制詳解

方法首先判斷當前任務狀態是否已經執行完成,如果執行完成則直接返回任務狀態。如果沒有執行完成,則從任務數組中(workQueue)取出任務并執行,任務執行完成則設置任務狀態為 NORMAL,如果出現異常則記錄異常并設置任務狀態為 EXCEPTIONAL(在 doExec() 方法中)。

總結

本文主要介紹了 Java 并發框架中的 Fork/Join 框架的基本原理和其使用的工作竊取算法(work-stealing)、設計方式和部分實現源碼。Fork/Join 框架在 JDK 的官方標準庫中也有應用。比如 JDK 1.8+ 標準庫提供的 Arrays.parallelSort(array) 可以進行并行排序,它的原理就是內部通過 Fork/Join 框架對大數組分拆進行并行排序,可以提高排序的速度,還有集合中的 Collection.parallelStream() 方法底層也是基于 Fork/Join 框架實現的,最后就是定義小任務的閾值往往是需要通過測試驗證才能合理給出,并且保證程序可以達到最好的性能。

到此這篇關于Java 并發中的Fork/Join 框架機制詳解的文章就介紹到這了,更多相關Java Fork/Join 框架內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
99国产一区| 国产精品a级| 日韩欧美少妇| а√在线中文在线新版| 麻豆一区在线| 久久精品女人| 国产丝袜一区| 国产精品一区二区三区av| 7777精品| 久久激情五月激情| 国产乱码精品一区二区亚洲| 日韩av电影一区| 国产探花在线精品| 久久久精品区| 国产高潮在线| 91精品久久久久久久久久不卡| 99热精品久久| 影音国产精品| 蜜臀精品一区二区三区在线观看| 免费看日韩精品| **爰片久久毛片| 日韩国产一二三区| 欧美国产亚洲精品| 日韩在线精品| 蜜桃视频欧美| 亚洲永久精品唐人导航网址| 日韩avvvv在线播放| 欧美黄色一区二区| 激情黄产视频在线免费观看| 亚洲视频综合| 在线免费观看亚洲| 国产亚洲精品美女久久| 精品欧美日韩精品| 久久久久免费av| 亚洲欧美日韩精品一区二区| 亚洲精品伦理| 国产精品日韩精品在线播放| 超碰99在线| 亚洲美洲欧洲综合国产一区| 日韩中文字幕在线一区| 国产精品nxnn| 日韩精品一卡| 亚洲91在线| 成人在线视频免费看| 欧美日韩激情| 91伊人久久| 精品国产第一福利网站| 99日韩精品| 国产日韩免费| 蜜桃精品在线| 香蕉久久久久久| 国产精品一区二区av交换| 日韩av自拍| 免费国产自线拍一欧美视频| 国产伦理一区| 亚洲一级黄色| 91精品福利观看| 欧美特黄一级大片| 91精品视频一区二区| 日韩欧美三级| 蜜桃久久久久久| 美女久久久久久| 欧美日韩国产亚洲一区| 国产人成精品一区二区三| 成人看片网站| 日韩激情一二三区| 97视频热人人精品免费| 一区二区高清| se01亚洲视频| 日韩中文字幕| 国产精品久久久久av电视剧| 日韩精品一级| 久久中文亚洲字幕| 国产精一区二区| 中文亚洲欧美| 国产精品成久久久久| 中文字幕中文字幕精品| 98精品视频| 欧美天堂一区| 欧美日韩在线二区| 欧美交a欧美精品喷水| 午夜国产欧美理论在线播放| 国产精区一区二区| 蜜臀av在线播放一区二区三区| 国产精品久久久久久久免费观看| 中文字幕日韩亚洲| 日韩毛片在线| 欧美经典一区| 日韩精品一区二区三区中文| 五月天综合网站| 精品免费在线| 奇米狠狠一区二区三区| 婷婷亚洲综合| 电影亚洲精品噜噜在线观看| 麻豆精品少妇| 日韩福利视频导航| 2023国产精品久久久精品双| 精品日韩一区| 国产区精品区| 日韩精品亚洲aⅴ在线影院| 最新国产拍偷乱拍精品| sm捆绑调教国产免费网站在线观看 | 亚洲影院天堂中文av色| 欧美手机在线| 欧美精品高清| 欧美国产中文高清| 日韩一区二区三区高清在线观看| 婷婷综合亚洲| 国产精品91一区二区三区| 色一区二区三区| 麻豆精品少妇| 国产高清精品二区| 国产伦理一区| 国产精品一线| 国产精品一国产精品k频道56| 日韩高清不卡在线| 91精品丝袜国产高跟在线| 日本欧美在线| 四虎国产精品免费久久| 亚州av日韩av| 日本大胆欧美人术艺术动态| 黄色免费成人| 狠狠久久婷婷| 亚洲欧洲午夜| 亚洲在线免费| 久久一二三区| 蜜臀av一区二区三区| 免费欧美在线视频| 亚洲一级淫片| 欧美精品三级在线| 欧美日韩亚洲三区| 国产视频一区二区在线播放| 国产精品视频首页| 欧美精品成人| 电影91久久久| 日产精品一区| 三上悠亚国产精品一区二区三区| 日韩伦理在线一区| 亚洲电影在线| 视频一区免费在线观看| 无码日韩精品一区二区免费| 综合激情婷婷| 欧美欧美黄在线二区| 国产极品久久久久久久久波多结野 | 99久久久久| 日韩一区二区免费看| 欧美综合国产| 日韩 欧美一区二区三区| 国产精一区二区| 国产亚洲久久| 国产精品久久久久蜜臀| 99视频精品全国免费| 亚洲免费在线| 午夜亚洲福利| 国产精品久久久久久模特 | 国产亚洲一区二区三区啪| 欧美视频久久| 国产成人免费| 婷婷色综合网| 视频一区欧美精品| 国产精品欧美在线观看| 韩国女主播一区二区三区| 国产精品久久久久av电视剧| 日韩一区二区免费看| 91免费精品国偷自产在线在线| 麻豆免费精品视频| 午夜av成人| 四虎精品永久免费| 日产精品一区二区| 亚洲综合不卡| 久久黄色影视| 九九色在线视频| 中文字幕亚洲精品乱码| 久久精品午夜| 高清av不卡| 欧美 日韩 国产一区二区在线视频 | 久久香蕉精品香蕉| 久久蜜桃精品| 日韩欧美中文在线观看| 国产成人免费视频网站视频社区| 欧美久久精品一级c片| 日本亚洲不卡| 美女精品一区二区| 婷婷色综合网| 国产欧美日韩免费观看| 亚洲天堂一区二区| 日韩一二三区在线观看| а√天堂8资源中文在线| 日韩在线卡一卡二| 91欧美在线| 视频一区欧美日韩| 国产网站在线| 亚洲精品乱码| 国产精品久久久久av电视剧| 日韩成人午夜精品| 999国产精品| 国产精品久久久久久模特 | 成人美女视频| 日韩精品导航| 久久精品高清|