? ? ? ? 本系列譯自jakob jenkov的Java并發(fā)多線程教程(本章節(jié)部分內(nèi)容參考http://ifeve.com/并發(fā)編程模型),個(gè)人覺(jué)得很有收獲洼怔。由于個(gè)人水平有限,不對(duì)之處還望矯正罐栈!? ?
? ? ? ? 并發(fā)系統(tǒng)可以有多種并發(fā)模型來(lái)實(shí)現(xiàn)豪嗽,并發(fā)模型指定線程如何協(xié)同完成分配給他們的任務(wù)。不同的并發(fā)模型以不同的方式劃分任務(wù)冕象,并且線程與線程之間以不同的方式進(jìn)行通信和協(xié)作代承。
并發(fā)模型與分布式系統(tǒng)的相似性
? ? ? ? ? 本文中描述的并發(fā)模型類(lèi)似于分布式系統(tǒng)中使用的不同體系結(jié)構(gòu)。在并發(fā)系統(tǒng)中渐扮,不同的線程彼此通信论悴。在分布式系統(tǒng)中,不同的進(jìn)程彼此通信(可能在不同的計(jì)算機(jī)上)墓律。線程和進(jìn)程在本質(zhì)上是非常相似的膀估。這就是為什么不同的并發(fā)模型通常看起來(lái)與不同的分布式系統(tǒng)體系結(jié)構(gòu)相似耻讽。
? ? ? ? 分布式系統(tǒng)在處理網(wǎng)絡(luò)失效察纯、遠(yuǎn)程主機(jī)或進(jìn)程宕掉等方面也面臨著額外的挑戰(zhàn)。但一個(gè)并發(fā)系統(tǒng)運(yùn)行在一個(gè)大型服務(wù)器中有可能也會(huì)遇到類(lèi)似的問(wèn)題,比如一塊 CPU 失效捐寥、一塊網(wǎng)卡失效或一個(gè)磁盤(pán)損壞等情況笤昨。雖然失敗的概率可能較低,但在理論上它仍然可能發(fā)生。
? ? ? ? 由于并發(fā)模型與分布式系統(tǒng)體系結(jié)構(gòu)相似握恳,所以它們常陈髦希可以互相借鑒。例如乡洼,為工作者們(線程)分配作業(yè)的模型一般與分布式系統(tǒng)中的負(fù)載均衡系統(tǒng)比較相似崇裁。同樣,它們?cè)谌罩居涗浭恰⑹мD(zhuǎn)移拔稳、冪等性等錯(cuò)誤處理技術(shù)上也具有相似性。
1锹雏、并行工作者(Parallel worker)
在并行worker模型中巴比,傳入的作業(yè)會(huì)被分配到不同的工作者,下圖展示并行工作者模型
在并行工作者模型中礁遵,委派者將傳入的作業(yè)分配給不同的工作者轻绞。每個(gè)工作者完成整個(gè)任務(wù),這些工作者并行運(yùn)行在不同的線程上佣耐,甚至可能不在同一個(gè)CPU上政勃。
? ? ? ? 如果在車(chē)廠利用并行工作者模型,那么每一輛車(chē)都是由一工人來(lái)完成的兼砖,這些工人都要有汽車(chē)的生產(chǎn)說(shuō)明書(shū)奸远,并且從頭到尾完成一輛車(chē)的生產(chǎn)。
? ? ? ? 并行工作者并發(fā)模型是Java應(yīng)用中最常用的一種并發(fā)模型(盡管這個(gè)情況在改變)讽挟。在java.util.concurrent包中的很多并發(fā)工具類(lèi)的目的是為了應(yīng)用這個(gè)模型懒叛。在Java企業(yè)版的服務(wù)器應(yīng)用中,也可以看到這個(gè)模型的蹤跡耽梅。
并行工作者模型的優(yōu)點(diǎn)
? ? ? 并行工作者模型的優(yōu)點(diǎn)是他容易理解芍瑞,如果想要增加應(yīng)用的并發(fā)規(guī)模,你只需要添加更多的工作者即可褐墅。
? ? ? 例如:你正在實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)爬蟲(chóng)拆檬,你可以通過(guò)多個(gè)工作者來(lái)爬一定數(shù)量的頁(yè)面,然后看在一定量的頁(yè)面情況下妥凳,調(diào)整工作者個(gè)數(shù)竟贯,看多少個(gè)工作者用時(shí)最短(意味著高性能),由于網(wǎng)絡(luò)爬蟲(chóng)是一種密集型IO任務(wù)逝钥,所以最終結(jié)果很可能是一個(gè)CPU中可以運(yùn)行多個(gè)爬蟲(chóng)線程屑那。這種情況下拱镐,如果一個(gè)CPU只有一個(gè)爬蟲(chóng)線程將會(huì)浪費(fèi)CPU資源,因?yàn)橄螺d數(shù)據(jù)通常會(huì)產(chǎn)生大量的CPU等待時(shí)間的持际。
并行工作者模型的缺點(diǎn)
? ? ? 并行工作的并發(fā)模型在其簡(jiǎn)單的外表下有一些隱藏缺點(diǎn)沃琅。我將在下面的內(nèi)容中闡述幾個(gè)最明顯的缺點(diǎn)。
A)共享狀態(tài)帶來(lái)了復(fù)雜性
? ? ? 在實(shí)際的的運(yùn)用中蜘欲,并行工作者模型遠(yuǎn)比上面的例子復(fù)雜益眉。共享工作者需要訪問(wèn)一些共享數(shù)據(jù),主些共享數(shù)據(jù)可能是內(nèi)存數(shù)據(jù)或是數(shù)據(jù)庫(kù)數(shù)據(jù)姥份。下面的圖來(lái)展示這樣的情形如何使得并行工作者變得更為復(fù)雜:
? ? ? ? 有時(shí)郭脂,這些共享狀態(tài)可能是通訊機(jī)制里的工作隊(duì)列,有時(shí)可能是業(yè)務(wù)數(shù)據(jù)澈歉,緩存數(shù)據(jù)展鸡,數(shù)據(jù)庫(kù)連接池等。
? ? ? ? 一旦并行工作者模型中有共享狀態(tài)埃难,那么將會(huì)變得很復(fù)雜莹弊,線程訪問(wèn)共享數(shù)據(jù),需要保證共享數(shù)據(jù)如果被一個(gè)線程更改涡尘,要對(duì)其他的線程可見(jiàn)(將修改結(jié)果同步到主存中忍弛,而不是當(dāng)前執(zhí)行線程的CPU緩存中)。線程間需要避免競(jìng)爭(zhēng)悟衩、死鎖和其他的一些因共享狀態(tài)并發(fā)問(wèn)題剧罩。
? ? ? ? 除此之外栓拜,部分并行線程在等待訪問(wèn)共享狀態(tài)時(shí)座泳,許多并發(fā)數(shù)據(jù)結(jié)構(gòu)被阻塞,這就意味著在同一時(shí)刻限制了其他線程對(duì)他們的訪問(wèn)幕与。這將導(dǎo)致線程對(duì)這些共享數(shù)據(jù)結(jié)構(gòu)的競(jìng)爭(zhēng)挑势,從本質(zhì)上講,高競(jìng)爭(zhēng)狀態(tài)會(huì)導(dǎo)致獲取共享數(shù)據(jù)的代碼在一定程度上串行化運(yùn)行啦鸣。
? ? ? ? 現(xiàn)行非阻塞式的并行算法有可能會(huì)減少競(jìng)爭(zhēng)和提高性能潮饱,但是非阻塞式的并行算法很難實(shí)現(xiàn) 。
? ? ? ? 持久化數(shù)據(jù)是另外一種選擇诫给,待久化數(shù)據(jù)結(jié)構(gòu)在修改之前通常會(huì)保存上一個(gè)版本的數(shù)據(jù)香拉,因些,如果多個(gè)線同時(shí)訪問(wèn)持久化數(shù)據(jù)時(shí)中狂,如果其中一個(gè)線程對(duì)數(shù)據(jù)進(jìn)行修改凫碌,修改的線程獲取這個(gè)數(shù)據(jù)結(jié)果的一個(gè)新的引用,而其他線程則保持原有數(shù)據(jù)結(jié)構(gòu)的引用胃榕。Scala語(yǔ)言具有幾種持久化的數(shù)據(jù)結(jié)構(gòu)盛险。
? ? ? 雖然持久化數(shù)據(jù)結(jié)構(gòu)是共享數(shù)據(jù)并發(fā)讀寫(xiě)中遇到的問(wèn)題的一個(gè)看似“優(yōu)雅的”解決方案,但其性能并不那么好。
? ? ? 例如:一個(gè)待久化的列表苦掘,添加一些新的元素到這個(gè)列表的頭部换帜,然后返回新加元素的引用。其他的線程仍舊保持持久化列表之前的引用鹤啡,因此對(duì)這些線程來(lái)說(shuō)惯驼,新添加的元素對(duì)他們是不可見(jiàn)的。
B)無(wú)狀態(tài)的工作者
? ? ? ? 由于共享狀態(tài)可能被系統(tǒng)中的其他線程修改揉忘。所以工作者在需要用到的時(shí)候必須重新去讀取這個(gè)狀態(tài)跳座,以確保當(dāng)前工作者運(yùn)行在最新的副本上。不管這個(gè)狀態(tài)是保存于內(nèi)存中泣矛,還是保存在外部的數(shù)據(jù)庫(kù)中疲眷,都是這樣去實(shí)現(xiàn)的。一個(gè)工作者您朽,不需要在線程內(nèi)部保存狀態(tài)(而是在需要用到的時(shí)候重新去讀瓤袼俊),這樣就稱(chēng)之為無(wú)狀態(tài)哗总。
? ? ? 每次重新去獲取共享數(shù)據(jù)的狀態(tài)會(huì)變慢几颜,尤其是共享狀態(tài)存儲(chǔ)在外部的數(shù)據(jù)庫(kù)中。
C) 工作順序是不確定的
? ? ? 并行工作者的另一個(gè)缺點(diǎn)就是工作順序的不確定讯屈。我們沒(méi)有辦法去保證任務(wù)按順序執(zhí)行蛋哭,例如:任務(wù)A有可能在任務(wù)B之前執(zhí)行,也有可能任務(wù)B先于任務(wù)A執(zhí)行涮母。
? ? ? 并于工作者模型的順序不確定性使得我們很難確定在給定的某個(gè)時(shí)間的狀態(tài)谆趾。并且也很難保證一個(gè)任務(wù)發(fā)生于另一個(gè)任務(wù)之前 。
2叛本、流水線模型
? ? ? ? 第二種并發(fā)模型稱(chēng)之為流水線模型沪蓬。我之所以取這個(gè)名字,只是為了配合“并行工作模型”来候。其他的程序員跷叉,可能會(huì)用其他名字。下圖表示一個(gè)流水線模型营搅。
? ? ? ? 像工作生產(chǎn)線上的工人們一樣組織工作者云挟,每個(gè)工作者只負(fù)責(zé)整個(gè)任務(wù)中的一部分,當(dāng)完成自己這部分的工作的工作者會(huì)將任務(wù)轉(zhuǎn)發(fā)給下一個(gè)工作者转质。每個(gè)工作者都在自己的線程中運(yùn)行园欣,并且不會(huì)和其他 的工作者共享狀態(tài)。因此有時(shí)也稱(chēng)之為無(wú)共享并行模型峭拘。
? ? ? ? 通常使用非阻塞的IO來(lái)設(shè)計(jì)使用流水線并發(fā)模型的系統(tǒng)俊庇。非阻塞意味著當(dāng)一個(gè)工作者操作IO時(shí)(比如:讀取文件或是從網(wǎng)絡(luò)連接中獲取數(shù)據(jù)),工作者不需要等到IO操作結(jié)束狮暑,由于IO操作非常慢,因此等待IO操作完成很浪費(fèi)CPU時(shí)間辉饱,在等待IO操作完成的同時(shí)搬男,CPU可以做些其他的事情,當(dāng)IO操作完成時(shí)彭沼,被傳遞給下一個(gè)工作者缔逛。
? ? ? ? 有了非阻塞IO,就可以使用IO操作來(lái)確定工作者之間的邊界姓惑。工作者會(huì)盡可能多的運(yùn)行直到遇到并啟動(dòng)一個(gè)IO操作褐奴。然后交出工作的控制權(quán),當(dāng)IO操作完成后于毙。然后在流水線上的下一個(gè)工作者繼續(xù)進(jìn)行操作敦冬。直到他也遇到并啟動(dòng)一個(gè)IO操作。
? ? ? 實(shí)事上唯沮,作業(yè)不可能沿著單一的流水線脖旱,由于多數(shù)的系統(tǒng)可能執(zhí)行多個(gè)作業(yè)。作業(yè)從一個(gè)工作者流向另一個(gè)工作者取決于作業(yè)需要做的工作介蛉。在實(shí)際中可能會(huì)有多個(gè)不同的虛擬流水線同時(shí)運(yùn)行萌庆。下面是現(xiàn)實(shí)中作業(yè)在流水線系統(tǒng)中可能的情況:
? ? ? ? 作業(yè)可能被轉(zhuǎn)發(fā)到多個(gè)工作者上并發(fā)處理。比如:作業(yè)可能同時(shí)被轉(zhuǎn)發(fā)到任務(wù)執(zhí)行器和作業(yè)日志币旧。下圖說(shuō)明了三條流水線是如何把一個(gè)作業(yè)轉(zhuǎn)發(fā)給同一個(gè)工作者(中間流水線的最后一個(gè)工作者)來(lái)完成作業(yè):
? ? ? ? 流水線作業(yè)有時(shí)會(huì)比這個(gè)更復(fù)雜
響應(yīng)(Reactive)践险,事件驅(qū)動(dòng)
? ? ? 采用流水線并發(fā)模型的系統(tǒng)有時(shí)也稱(chēng)之為Reactive或是事件驅(qū)動(dòng)系統(tǒng)。系統(tǒng)中的工作者會(huì)對(duì)來(lái)自系統(tǒng)內(nèi)部的事件吹菱,或者接受外部的請(qǐng)求或者其他工作傳入的事件做出響應(yīng)巍虫。舉個(gè)例子:事件有可能是來(lái)自于外部的HTTP請(qǐng)求,也有可能是某個(gè)文件成功加載到內(nèi)存中毁葱。
Actors vs. Channels
? ? ? Actors和Channels是兩種比較類(lèi)似的流水線(Reactive/事件驅(qū)動(dòng))模型垫言。在Actor模型中每個(gè)工作者被稱(chēng)之為actor贰剥,Actor之間可以異步發(fā)送和處理消息倾剿。actor可以被用來(lái)實(shí)現(xiàn)一個(gè)或多個(gè)流水線作業(yè)。下圖給出了actor模型的:
? ? ? 而在channel模型中蚌成。工作者之間不直接與其他工作者通信前痘。而是他們把他們的消息(事件)發(fā)布到另一個(gè)不同的channel,其他工作者可以監(jiān)聽(tīng)在這個(gè)channel上担忧,而發(fā)布者不需要知道是誰(shuí)在監(jiān)聽(tīng)芹缔。下圖給出了channel模型:
? ? ? 在寫(xiě)這篇文章的時(shí)候,channel模型對(duì)于我來(lái)說(shuō)似乎更加靈活瓶盛。一個(gè)工作者無(wú)需知道誰(shuí)在后面的流水線上處理作業(yè)最欠。只需知道作業(yè)(或消息等)需要轉(zhuǎn)發(fā)給哪個(gè)通道示罗。通道上的監(jiān)聽(tīng)者可以隨意訂閱或者取消訂閱,并不會(huì)影響向這個(gè)通道發(fā)送消息的工作者芝硬。這使得工作者之間具有松散的耦合蚜点。
流水線模型的優(yōu)點(diǎn)
? ? ? 相對(duì)于并行工作者模型,流水線模型具有幾個(gè)優(yōu)點(diǎn)拌阴,在接下來(lái)的章節(jié)中我會(huì)介紹幾個(gè)最大的優(yōu)點(diǎn)绍绘。
無(wú)共享狀態(tài)
? ? ? 工作者之間無(wú)狀態(tài)。意味著實(shí)現(xiàn)的時(shí)候無(wú)需考慮所有因并發(fā)訪問(wèn)共享對(duì)象而產(chǎn)生的并發(fā)性問(wèn)題迟赃。這使得在實(shí)現(xiàn)工作者的時(shí)候變得非常容易陪拘。在實(shí)現(xiàn)工作的時(shí)候就好像是單個(gè)線程在處理工作一樣,這基本上是一個(gè)單線程的實(shí)現(xiàn) 纤壁。
有狀態(tài)的工作者
? ? ? ? 當(dāng)工作者知道沒(méi)有別的線程修改它們的數(shù)據(jù)左刽,工作者可以是有狀態(tài)的,對(duì)于有狀態(tài)酌媒,我的意思是悠反,它們可以在內(nèi)存中保存要操作的數(shù)據(jù),只需要在最后把更改的結(jié)果寫(xiě)回到外部存儲(chǔ)系統(tǒng)馍佑。因此斋否,有狀態(tài)的工作者通常比無(wú)狀態(tài)的工作者更快。
更好的與硬件結(jié)合
? ? ? ? 單線程代碼通常在結(jié)合底層硬件時(shí)具有更好的優(yōu)勢(shì)拭荤。首先茵臭,當(dāng)你假設(shè)代碼只在單線程模型下運(yùn)行時(shí),通常能能創(chuàng)建更優(yōu)的數(shù)據(jù)結(jié)構(gòu)和算法 舅世。
? ? ? 其次旦委,單線程的工作者可以緩存數(shù)據(jù)到內(nèi)存中,當(dāng)數(shù)據(jù)緩存在內(nèi)存中雏亚,有很大的可能數(shù)據(jù)也緩存在執(zhí)行這個(gè)線程的CPU中缨硝,這使得訪問(wèn)緩存數(shù)據(jù)變得很快。
合理的作業(yè)順序
? ? ? 基于流水線并發(fā)模型實(shí)現(xiàn)的并發(fā)系統(tǒng)罢低,在某種程度上是有可能保證作業(yè)的順序的查辩。作業(yè)的有序性使得它更容易地推出系統(tǒng)在某個(gè)特定時(shí)間點(diǎn)的狀態(tài)。更進(jìn)一步网持,你可以將所有到達(dá)的作業(yè)寫(xiě)入到日志中去宜岛。一旦這個(gè)系統(tǒng)的某一部分掛掉了,該日志就可以用來(lái)重頭開(kāi)始重建系統(tǒng)當(dāng)時(shí)的狀態(tài)功舀。按照特定的順序?qū)⒆鳂I(yè)寫(xiě)入日志萍倡,并按這個(gè)順序作為有保障的作業(yè)順序。下圖展示了一種可能的設(shè)計(jì):
? ? ? 實(shí)現(xiàn)一個(gè)有保障的作業(yè)順序是不容易的辟汰,但往往是可行的列敲。如果可以阱佛,它 將大大簡(jiǎn)化一些任務(wù),例如備份戴而、數(shù)據(jù)恢復(fù)瘫絮、數(shù)據(jù)復(fù)制等,這些都可以通過(guò)日志文件來(lái)完成填硕。
流水線模型的缺點(diǎn)
? ? ? 流水線并發(fā)模型最大的缺點(diǎn)是作業(yè)的執(zhí)行往往分布到多個(gè)工作者上麦萤,并因此分布到項(xiàng)目中的多個(gè)類(lèi)上。這樣導(dǎo)致在追蹤某個(gè)作業(yè)到底被什么代碼執(zhí)行時(shí)變得困難扁眯。
? ? ? ? 流水線并發(fā)模型最大的缺點(diǎn)是作業(yè)的執(zhí)行往往分布到多個(gè)工作者上壮莹,并因此分布到項(xiàng)目中的多個(gè)類(lèi)上。這樣導(dǎo)致在追蹤某個(gè)作業(yè)到底被什么代碼執(zhí)行時(shí)變得困難姻檀。
? ? ? 使用并行工作者模型可以簡(jiǎn)化這個(gè)問(wèn)題命满。你可以打開(kāi)工作者的代碼,從頭到尾優(yōu)美的閱讀被執(zhí)行的代碼绣版。當(dāng)然并行工作者模式的代碼也可能同樣分布在不同的類(lèi)中胶台,但往往也能夠很容易的從代碼中分析執(zhí)行的順序。
3杂抽、函數(shù)式并行(Functional Parallelism)
? ? ? 第三種并發(fā)模型是函數(shù)式并行模型诈唬。函數(shù)式并行的基本思想是采用函數(shù)調(diào)用實(shí)現(xiàn)程序。函數(shù)可以看作是”代理人(agents)“或者”actor“缩麸,函數(shù)之間可以像流水線模型(AKA 反應(yīng)器或者事件驅(qū)動(dòng)系統(tǒng))那樣互相發(fā)送消息铸磅。某個(gè)函數(shù)調(diào)用另一個(gè)函數(shù),這個(gè)過(guò)程類(lèi)似于消息發(fā)送杭朱。
? ? ? 函數(shù)都是通過(guò)拷貝來(lái)傳遞參數(shù)的阅仔,所以除了接收函數(shù)外沒(méi)有實(shí)體可以操作數(shù)據(jù)。這對(duì)于避免共享數(shù)據(jù)的競(jìng)態(tài)來(lái)說(shuō)是很有必要的弧械。同樣也使得函數(shù)的執(zhí)行類(lèi)似于原子操作八酒。每個(gè)函數(shù)調(diào)用的執(zhí)行獨(dú)立于任何其他函數(shù)的調(diào)用。
? ? ? ? 一旦每個(gè)函數(shù)調(diào)用都可以獨(dú)立的執(zhí)行刃唐,它們就可以分散在不同的CPU上執(zhí)行了羞迷。這也就意味著能夠在多處理器上并行的執(zhí)行使用函數(shù)式實(shí)現(xiàn)的算法。
? ? ? ? Java7中的java.util.concurrent包里包含的ForkAndJoinPool能夠幫助我們實(shí)現(xiàn)類(lèi)似于函數(shù)式并行的一些東西唁桩。而Java8中并行streams能夠用來(lái)幫助我們并行的迭代大型集合闭树。
? ? ? 函數(shù)式并行里面最難的是確定需要并行的那個(gè)函數(shù)調(diào)用耸棒』脑瑁跨CPU協(xié)調(diào)函數(shù)調(diào)用需要一定的開(kāi)銷(xiāo)。某個(gè)函數(shù)完成的工作單元需要達(dá)到某個(gè)大小以彌補(bǔ)這個(gè)開(kāi)銷(xiāo)与殃。如果函數(shù)調(diào)用作用非常小单山,將它并行化可能比單線程碍现、單CPU執(zhí)行還慢。
? ? ? ? 我個(gè)人認(rèn)為(可能不太正確)米奸,你可以使用響應(yīng)模型(Reactive)或者事件驅(qū)動(dòng)模型實(shí)現(xiàn)一個(gè)算法昼接,像函數(shù)式并行那樣的方法實(shí)現(xiàn)工作的分解。使用事件驅(qū)動(dòng)模型可以更精確的控制如何實(shí)現(xiàn)并行化(我的觀點(diǎn))悴晰。
? ? ? ? 此外慢睡,將任務(wù)拆分給多個(gè)CPU時(shí)協(xié)調(diào)造成的開(kāi)銷(xiāo),僅僅在該任務(wù)是程序當(dāng)前執(zhí)行的唯一任務(wù)時(shí)才有意義铡溪。但是漂辐,如果當(dāng)前系統(tǒng)正在執(zhí)行多個(gè)其他的任務(wù)時(shí)(比如web服務(wù)器,數(shù)據(jù)庫(kù)服務(wù)器或者很多其他類(lèi)似的系統(tǒng))棕硫,將單個(gè)任務(wù)進(jìn)行并行化是沒(méi)有意義的髓涯。不管怎樣計(jì)算機(jī)中的其他CPU們都在忙于處理其他任務(wù),沒(méi)有理由用一個(gè)慢的哈扮、函數(shù)式并行的任務(wù)去擾亂它們纬纪。使用流水線(反應(yīng)器)并發(fā)模型可能會(huì)更好一點(diǎn),因?yàn)樗_(kāi)銷(xiāo)更谢狻(在單線程模式下順序執(zhí)行)同時(shí)能更好的與底層硬件整合包各。
使用那種并發(fā)模型最好?
? ? ? ? 所以靶庙,用哪種并發(fā)模型更好呢?
? ? ? ? 通常情況下髓棋,這個(gè)答案取決于你的系統(tǒng)打算做什么。如果你的作業(yè)本身就是并行的惶洲、獨(dú)立的并且沒(méi)有必要共享狀態(tài)按声,你可能會(huì)使用并行工作者模型去實(shí)現(xiàn)你的系統(tǒng)。雖然許多作業(yè)都不是自然并行和獨(dú)立的恬吕。對(duì)于這種類(lèi)型的系統(tǒng)签则,我相信使用流水線并發(fā)模型能夠更好的發(fā)揮它的優(yōu)勢(shì),而且比并行工作者模型更有優(yōu)勢(shì)铐料。
? ? ? ? 你甚至不用親自編寫(xiě)所有流水線模型的基礎(chǔ)結(jié)構(gòu)渐裂。像Vert.x這種現(xiàn)代化的平臺(tái)已經(jīng)為你實(shí)現(xiàn)了很多。我也會(huì)去為探索如何設(shè)計(jì)我的下一個(gè)項(xiàng)目钠惩,使它運(yùn)行在像Vert.x這樣的優(yōu)秀平臺(tái)上柒凉。