cake fork什么意思_Java7任务并行执行神器:Forkamp;Join框架
Fork/Join是什么?
Fork/Join框架是Java7提供的并行執(zhí)行任務(wù)框架,思想是將大任務(wù)分解成小任務(wù),然后小任務(wù)又可以繼續(xù)分解,然后每個(gè)小任務(wù)分別計(jì)算出結(jié)果再合并起來(lái),最后將匯總的結(jié)果作為大任務(wù)結(jié)果。其思想和MapReduce的思想非常類(lèi)似。對(duì)于任務(wù)的分割,要求各個(gè)子任務(wù)之間相互獨(dú)立,能夠并行獨(dú)立地執(zhí)行任務(wù),互相之間不影響。
Fork/Join的運(yùn)行流程圖如下:
我們可以通過(guò)Fork/Join單詞字面上的意思去理解這個(gè)框架。Fork是叉子分叉的意思,即將大任務(wù)分解成并行的小任務(wù),Join是連接結(jié)合的意思,即將所有并行的小任務(wù)的執(zhí)行結(jié)果匯總起來(lái)。
工作竊取算法
ForkJoin采用了工作竊取(work-stealing)算法,若一個(gè)工作線程的任務(wù)隊(duì)列為空沒(méi)有任務(wù)執(zhí)行時(shí),便從其他工作線程中獲取任務(wù)主動(dòng)執(zhí)行。為了實(shí)現(xiàn)工作竊取,在工作線程中維護(hù)了雙端隊(duì)列,竊取任務(wù)線程從隊(duì)尾獲取任務(wù),被竊取任務(wù)線程從隊(duì)頭獲取任務(wù)。這種機(jī)制充分利用線程進(jìn)行并行計(jì)算,減少了線程競(jìng)爭(zhēng)。但是當(dāng)隊(duì)列中只存在一個(gè)任務(wù)了時(shí),兩個(gè)線程去取反而會(huì)造成資源浪費(fèi)。
工作竊取的運(yùn)行流程圖如下:
Fork/Join核心類(lèi)
Fork/Join框架主要由子任務(wù)、任務(wù)調(diào)度兩部分組成,類(lèi)層次圖如下。
- ForkJoinPool
ForkJoinPool是ForkJoin框架中的任務(wù)調(diào)度器,和ThreadPoolExecutor一樣實(shí)現(xiàn)了自己的線程池,提供了三種調(diào)度子任務(wù)的方法:
Fork/Join框架中的實(shí)際的執(zhí)行任務(wù)類(lèi),有以下兩種實(shí)現(xiàn),一般繼承這兩種實(shí)現(xiàn)類(lèi)即可。
Fork/Join框架實(shí)戰(zhàn)
下面實(shí)現(xiàn)一個(gè)Fork/Join小例子,從1+2+...10億,每個(gè)任務(wù)只能處理1000個(gè)數(shù)相加,超過(guò)1000個(gè)的自動(dòng)分解成小任務(wù)并行處理;并展示了通過(guò)不使用Fork/Join和使用時(shí)的時(shí)間損耗對(duì)比。
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;public class ForkJoinTask extends RecursiveTask<Long> {private static final long MAX = 1000000000L;private static final long THRESHOLD = 1000L;private long start;private long end;public ForkJoinTask(long start, long end) {this.start = start;this.end = end;}public static void main(String[] args) {test();System.out.println("--------------------");testForkJoin();}private static void test() {System.out.println("test");long start = System.currentTimeMillis();Long sum = 0L;for (long i = 0L; i <= MAX; i++) {sum += i;}System.out.println(sum);System.out.println(System.currentTimeMillis() - start + "ms");}private static void testForkJoin() {System.out.println("testForkJoin");long start = System.currentTimeMillis();ForkJoinPool forkJoinPool = new ForkJoinPool();Long sum = forkJoinPool.invoke(new ForkJoinTask(1, MAX));System.out.println(sum);System.out.println(System.currentTimeMillis() - start + "ms");}@Overrideprotected Long compute() {long sum = 0;if (end - start <= THRESHOLD) {for (long i = start; i <= end; i++) {sum += i;}return sum;} else {long mid = (start + end) / 2;ForkJoinTask task1 = new ForkJoinTask(start, mid);task1.fork();ForkJoinTask task2 = new ForkJoinTask(mid + 1, end);task2.fork();return task1.join() + task2.join();}}}這里需要計(jì)算結(jié)果,所以任務(wù)繼承的是RecursiveTask類(lèi)。ForkJoinTask需要實(shí)現(xiàn)compute方法,在這個(gè)方法里首先需要判斷任務(wù)是否小于等于閾值1000,如果是就直接執(zhí)行任務(wù)。否則分割成兩個(gè)子任務(wù),每個(gè)子任務(wù)在調(diào)用fork方法時(shí),又會(huì)進(jìn)入compute方法,看看當(dāng)前子任務(wù)是否需要繼續(xù)分割成孫任務(wù),如果不需要繼續(xù)分割,則執(zhí)行當(dāng)前子任務(wù)并返回結(jié)果。使用join方法會(huì)阻塞并等待子任務(wù)執(zhí)行完并得到其結(jié)果。
程序輸出:
test 500000000500000000 4992ms -------------------- testForkJoin 500000000500000000 508ms從結(jié)果看出,并行的時(shí)間損耗明顯要少于串行的,這就是并行任務(wù)的好處。
盡管如此,在使用Fork/Join時(shí)也得注意,不要盲目使用。
更多Java好文請(qǐng)關(guān)注Java技術(shù)棧微信公眾號(hào),在公眾號(hào)后臺(tái)回復(fù)關(guān)鍵字:java,以下僅為部分預(yù)覽。
- 出場(chǎng)率比較高的一道多線程安全面試題
- Java類(lèi)初始化順序,大神3個(gè)示例帶你躺坑
- switch case 支持的 6 種數(shù)據(jù)類(lèi)型!
- 面試常考:Synchronized 有幾種用法?
- Hashtable 為什么不叫 HashTable?
本文原創(chuàng)首發(fā)于微信公眾號(hào):Java技術(shù)棧(id:javastack),轉(zhuǎn)載請(qǐng)?jiān)瓨颖A舯拘畔ⅰ?/p>
總結(jié)
以上是生活随笔為你收集整理的cake fork什么意思_Java7任务并行执行神器:Forkamp;Join框架的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: postman安装_Postman插件的
- 下一篇: stringredistemplate设