[转]Java7中的ForkJoin并发框架初探(上)——需求背景和设计原理
詳見: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp83
這篇我們來簡要了解一下JavaSE7中提供的一個(gè)新特性 —— Fork Join 框架。
0. 處理器發(fā)展和需求背景
回想一下并發(fā)開發(fā)的初衷,其實(shí)可以說是有兩點(diǎn),或者說可以從兩個(gè)方面看。
- 對(duì)于單核的處理器來說,在進(jìn)行IO操作等比較費(fèi)時(shí)的操作進(jìn)行時(shí),如果執(zhí)行任務(wù)的方式是單任務(wù)的,那么CPU將會(huì)“空轉(zhuǎn)”,知道IO操作結(jié)束。如果有多任務(wù)的調(diào)度機(jī)制,則在一個(gè)任務(wù)不需要CPU支持的時(shí)候,CPU可以被調(diào)度處理其他任務(wù)。簡單地講,并發(fā)可以提高CPU計(jì)算資源的利用率。
- 對(duì)于多核,或者多個(gè)計(jì)算資源的情況下,并發(fā)可以在某種程度上達(dá)到“并行”,即同時(shí)運(yùn)行,縮短了任務(wù)完成的時(shí)間,提高了任務(wù)完成的效率。
我們?cè)賮砜匆幌绿幚砥饔?jì)算能力的發(fā)展(講并發(fā)或者并行基本都要提到),Intel的創(chuàng)始人之一Gordon Moore曾經(jīng)說過一句話,大概意思是:
當(dāng)價(jià)格不變時(shí),集成電路上可容納的晶體管數(shù)目,約每隔18個(gè)月便會(huì)增加一倍,性能也將提升一倍。
我們可以這樣理解,處理器的計(jì)算能力在一定意義上和芯片上集成的晶體管數(shù)量有關(guān),而這項(xiàng)繼承技術(shù)的發(fā)展史飛快的。但是,什么事情都是有一個(gè)極限的,提升計(jì)算性能僅僅靠增加晶體管數(shù)量提高處理器主頻是不現(xiàn)實(shí)的,于是多核處理器的概念就出來了。
隨著在硬件上多核處理器的發(fā)展和廣泛使用,軟件開發(fā)上的變革也在進(jìn)行。簡單來想,對(duì)于多個(gè)不相關(guān)的小任務(wù)來講,可以分派到不同的處理器核心來進(jìn)行處理。然而,對(duì)于一個(gè)比較大的任務(wù),如何能夠充分利用多核計(jì)算資源就是一個(gè)值得考慮的問題。
解決這個(gè)問題的辦法就是“分而治之”,而Fork Join正式這樣一種思路的產(chǎn)物。
1. Fork Join 的設(shè)計(jì)簡介
看過《Introduction to Algorithms》(《算法導(dǎo)論》)的朋友們應(yīng)該還記得,在講到歸并排序(Merge Sort)和快速排序的時(shí)候,有一種很簡單又很有效率的思路就是“分而治之”,即“分治法”。而Fork Join的思路也是同理,只不過劃分之后的任務(wù)更適合分派給不同的計(jì)算資源,可以并行的完成任務(wù)。
ForkJoin的任務(wù)分解和合并
當(dāng)計(jì)算分別完成之后,最后再合并回來。
簡單來看,就是一個(gè)遞歸的分解和合并,知道任務(wù)小到可以接受的程度。
2. Fork Join 設(shè)計(jì)要點(diǎn)
Fork Join設(shè)計(jì)出來就是為了提高任務(wù)完成的效率,圍繞這個(gè)目標(biāo),有一些要點(diǎn)是設(shè)計(jì)中需要考慮的,下面就給出一些要點(diǎn)。
- 線程的管理和線程的單純性。基于如上的設(shè)計(jì)思路,我們可以看到子任務(wù)之間的相關(guān)性是相對(duì)比較簡單的,可以并行處理。為了提高效率,并不需要重量級(jí)的線程結(jié)構(gòu)和對(duì)應(yīng)的線程維護(hù),線程實(shí)現(xiàn)簡單就好,滿足需求即可,降低維護(hù)成本。
- 隊(duì)列機(jī)制,硬件支持一定是比較有限的,那么分解的任務(wù)應(yīng)該用隊(duì)列維護(hù)起來,一個(gè)好的隊(duì)列設(shè)計(jì)是很有必要的。
- “工作竊取”,也就是設(shè)計(jì)論文原文中提到的 Work Stealing 。對(duì)于負(fù)載比較輕的線程,可以幫助負(fù)載較重的執(zhí)行線程分擔(dān)任務(wù)。
對(duì)于使用Fork Join的開發(fā)者來講,需要注意:
- 可用線程數(shù)和硬件支持。線程這東西,也是有開銷的東西,絕對(duì)不是越多越好,尤其在硬件基礎(chǔ)有限的情況下。
- 任務(wù)分解的粒度。和前者有關(guān)系,就是分解的任務(wù),“小”到什么程度是可以接受的,不可再分。
3. Fork Join數(shù)據(jù)結(jié)構(gòu)支持
按照如上設(shè)計(jì),分解執(zhí)行一個(gè)大的任務(wù),Fork Join至少需要考慮如下一些數(shù)據(jù)結(jié)構(gòu)。
- 輕量級(jí)的線程結(jié)構(gòu)。
- 維護(hù)線程的線程池,負(fù)責(zé)線程的創(chuàng)建,數(shù)量維護(hù)和任務(wù)管理。
- 維護(hù)任務(wù),并支持Work Stealing的雙端隊(duì)列。如下圖。
支持ForkJoin任務(wù)維護(hù)的雙端隊(duì)列Deque
對(duì)于子任務(wù)的分解,可以從后端取出分解再放入,而對(duì)于WorkStealing則可以從頭部取出,放入其他隊(duì)列的尾部。
到此,本文僅僅是對(duì)Fork Join的大致設(shè)計(jì)思路做一個(gè)描述、勾勒。下一篇文章中會(huì)對(duì)JDK1.7中給出的實(shí)現(xiàn)作出分析。
轉(zhuǎn)載于:https://www.cnblogs.com/grefr/p/5046286.html
總結(jié)
以上是生活随笔為你收集整理的[转]Java7中的ForkJoin并发框架初探(上)——需求背景和设计原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安装了多个Oracle11g的客户端,哪
- 下一篇: 集算器协助Java处理结构化文本之条件过