本篇文章給大家分享的是有關(guān)java J.U.C中ForkJoin的使用分析,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
十年來,創(chuàng)新互聯(lián)不忘初心,以網(wǎng)站建設(shè)互聯(lián)網(wǎng)行業(yè)服務(wù)標桿為目標,不斷提升技術(shù)設(shè)計服務(wù)水平,幫助客戶在互聯(lián)網(wǎng)推廣自己的產(chǎn)品、服務(wù)和品牌,為客戶創(chuàng)造價值從而實現(xiàn)自身價值!
ForkJoin框架是Java7提供的一個用于并行執(zhí)行任務(wù)的框架,是一個把大任務(wù)分割成若干個小任務(wù),最終匯總每個小任務(wù)結(jié)果后得到大任務(wù)結(jié)果的框架。
與MapReduce思想非常類似。從字面意思上看,F(xiàn)ork就是把一個大任務(wù)切割成若干個子任務(wù)并行執(zhí)行,Join就是合并這些子任務(wù)的執(zhí)行結(jié)果,最后得到大任務(wù)的結(jié)果。主要采用工作竊取算法。
工作竊取算法是指某個線程從其他隊列里竊取任務(wù)來執(zhí)行。下面是工作竊取的流程圖:
為什么要使用工作竊取算法?
加入我們需要做一個比較大的任務(wù),我們可以把這個任務(wù)分割成若干個互不依賴的子任務(wù),為了減少線程間的競爭,于是把這些子任務(wù)分別放到不同的隊列里,為每個隊列創(chuàng)建一個單獨的線程來執(zhí)行隊列里面的任務(wù),線程和隊列一一對應(yīng)。比如A線程負責(zé)處理A隊列里面的任務(wù),但是有些線程會先把自己的隊列里面的任務(wù)干完,而其他線程還有對應(yīng)的任務(wù)等待處理,干完活的線程就會幫其他線程干活,于是就會去其他線程的隊列里竊取一個任務(wù)來執(zhí)行,這時他們會訪問同一個隊列,所以為了減少竊取任務(wù)線程與被竊取任務(wù)線程之間的競爭,通常會使用雙端隊列,被竊取任務(wù)的線程永遠從雙端隊列的頭部拿任務(wù)執(zhí)行,而竊取任務(wù)的線程永遠從雙端隊列的尾部拿任務(wù)執(zhí)行。這種優(yōu)點就是充分利用線程進行并行計算,減少了線程間的競爭,缺點是在某些情況下還是存在競爭(比如在雙端隊列只有一個任務(wù)時),同時也消耗了更多的系統(tǒng)資源(比如創(chuàng)建了多個線程和多個雙端隊列)。
對于ForkJoin框架而言,當一個任務(wù)正在等待他使用ForkJoin操作創(chuàng)建的子任務(wù)結(jié)束時,執(zhí)行這個任務(wù)的工作線程查找其他未被執(zhí)行的任務(wù),并開始他的執(zhí)行,通過這種方式,線程充分利用他的運行時間來提高應(yīng)用程序的性能,為了實現(xiàn)這個目標ForkJoin框架執(zhí)行的任務(wù)有一些局限性。
任務(wù)只能使用Fork和Join操作來作為同步機制,如果使用了其他同步機制,那他們在同步操作時工作線程就不能執(zhí)行其他任務(wù)了。比如在forkjoin框架中使任務(wù)進入sleep,在睡眠期間內(nèi)正在執(zhí)行這個任務(wù)的工作線程將不會執(zhí)行其他任務(wù)了。
我們所拆分的任務(wù)不應(yīng)該去執(zhí)行IO操作。例如讀寫數(shù)據(jù)文件
任務(wù)不能拋出檢查異常。必須通過必要的代碼來處理他們
ForkJoin框架的核心是兩個類:ForkJoinPool和ForkJoinTask。ForkJoinPool負責(zé)做實現(xiàn)(包括工作竊取算法)他管理工作線程提供任務(wù)的狀態(tài)以及他們的執(zhí)行信息。而ForkJoinTask則主要提供在任務(wù)中執(zhí)行Fork和Join操作的機制。
@Slf4j public class ForkJoinTaskExample extends RecursiveTask<Integer> { public static final int threshold = 2; private int start; private int end; public ForkJoinTaskExample(int start, int end) { this.start = start; this.end = end; } @Override protected Integer compute() { int sum = 0; //如果任務(wù)足夠小就計算任務(wù) boolean canCompute = (end - start) <= threshold; if (canCompute) { for (int i = start; i <= end; i++) { sum += i; } } else { // 如果任務(wù)大于閾值,就分裂成兩個子任務(wù)計算 int middle = (start + end) / 2; ForkJoinTaskExample leftTask = new ForkJoinTaskExample(start, middle); ForkJoinTaskExample rightTask = new ForkJoinTaskExample(middle + 1, end); // 執(zhí)行子任務(wù) leftTask.fork(); rightTask.fork(); //等待任務(wù)執(zhí)行結(jié)束合并其結(jié)果 int leftResult = leftTask.join(); int rightResult = rightTask.join(); // 合并子任務(wù) sum = leftResult + rightResult; } return sum; } public static void main(String[] args) { ForkJoinPool forkJoinPool = new ForkJoinPool(); //生成一個計算任務(wù),計算1+2+3+4...+100 ForkJoinTaskExample taskExample = new ForkJoinTaskExample(1, 100); Future<Integer> result = forkJoinPool.submit(taskExample); try{ log.info("result:{}", result.get()); } catch (InterruptedException e) { log.error("exception", e); e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
以上就是java J.U.C中ForkJoin的使用分析,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)頁題目:javaJ.U.C中ForkJoin的使用分析
網(wǎng)站網(wǎng)址:http://aaarwkj.com/article32/peihsc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、動態(tài)網(wǎng)站、、網(wǎng)站設(shè)計公司、網(wǎng)站維護、營銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)