說到并行茎芋,常見的幾種模式 “回調(diào)驅(qū)動(dòng)(多線程環(huán)境下)”颅眶、“消息/事件驅(qū)動(dòng)(Actor模型中)蜈出。
回調(diào)是最常見的異步并發(fā)模式,它有即時(shí)性高涛酗、接口設(shè)計(jì)簡(jiǎn)單等有點(diǎn)铡原。但相對(duì)于Future,其缺點(diǎn)也非常明顯商叹。
首先燕刻,多線程環(huán)境下的回調(diào)一般是在觸發(fā)回調(diào)的模塊線程中執(zhí)行的,這就意味著編寫回調(diào)方法時(shí)通常必須考慮線程互斥問題
其次剖笙,回調(diào)方式接口的提供者在本模塊的線程中執(zhí)行用戶應(yīng)用的回調(diào)也是相對(duì)不安全的卵洗,因?yàn)槟銦o法確定它會(huì)花費(fèi)多長(zhǎng)時(shí)間或出現(xiàn)什么異常,從而可能間接導(dǎo)致本模塊的即時(shí)性和可靠性受影響弥咪;
再者过蹂,使用回調(diào)接口不利于順序流程的開發(fā),因?yàn)榛卣{(diào)方法的執(zhí)行是孤立的聚至,要與正常流程匯合是比較困難的酷勺。因此回調(diào)接口適合于在回調(diào)中只需要完成簡(jiǎn)單任務(wù),并且不必與其它流程匯合的場(chǎng)景扳躬。
Future對(duì)象本身可以看作是一個(gè)顯式的引用脆诉,一個(gè)對(duì)異步處理結(jié)果的引用,可以通過調(diào)用Future.isDone()判斷引用的對(duì)象是否就緒甚亭,并采取不同的處理;而后一種情況則只需調(diào)用get()或
get(long timeout, TimeUnit unit)通過同步阻塞方式等待對(duì)象就緒击胜。實(shí)際運(yùn)行期是阻塞還是立即返回就取決于get()的調(diào)用時(shí)機(jī)和對(duì)象就緒的先后了.
Future的衍生
除了上面提到的基礎(chǔ)形態(tài)之外亏狰,F(xiàn)uture還有豐富的衍生變化,這里就列舉幾個(gè)常見的偶摔。
Lazy Future
與一般的Future不同骚揍,Lazy Future在創(chuàng)建之初不會(huì)主動(dòng)開始準(zhǔn)備引用的對(duì)象,而是等到請(qǐng)求對(duì)象時(shí)才開始相應(yīng)的工作啰挪。因此信不,Lazy Future本身并不是為了實(shí)現(xiàn)并發(fā),而是以節(jié)約不必要的運(yùn)算資源為出發(fā)點(diǎn)亡呵,效果上與Lambda/Closure類似抽活。例如設(shè)計(jì)某些API時(shí),你可能需要返回一組信息锰什,而其中某些信息的計(jì)算可能會(huì)耗費(fèi)可觀的資源下硕。但調(diào)用者不一定都關(guān)心所有的這些信息,因此將那些需要耗費(fèi)較多資源的對(duì)象以Lazy Future的形式提供汁胆,可以在調(diào)用者不需要用到特定的信息時(shí)節(jié)省資源梭姓。
另外Lazy Future也可以用于避免過早的獲取或鎖定資源而產(chǎn)生的不必要的互斥。
Promise
Promise可以看作是Future的一個(gè)特殊分支嫩码,常見的Future一般是由服務(wù)調(diào)用者直接觸發(fā)異步處理流程誉尖,比如調(diào)用服務(wù)時(shí)立即觸發(fā)處理或 Lazy Future的取值時(shí)觸發(fā)處理。但Promise則用于顯式表示那些異步流程并不直接由服務(wù)調(diào)用者觸發(fā)的情景铸题。例如Future接口的定時(shí)控制铡恕,其異步流程不是由調(diào)用者,而是由系統(tǒng)時(shí)鐘觸發(fā)丢间,再比如淘寶的分布式訂閱框架提供的Future式訂閱接口探熔,其等待數(shù)據(jù)的可用性不是由訂閱者決定,而在于發(fā)布者何時(shí)發(fā)布或更新數(shù)據(jù)烘挫。因此诀艰,相對(duì)于標(biāo)準(zhǔn)的Future,Promise接口一般會(huì)多出一個(gè)set()或fulfill()接口饮六。
可復(fù)用的Future
常規(guī)的Future是一次性的其垄,也就是說當(dāng)你獲得了異步的處理結(jié)果后,F(xiàn)uture對(duì)象本身就失去意義了喜滨。但經(jīng)過特殊設(shè)計(jì)的Future也可以實(shí)現(xiàn)復(fù)用捉捅,這對(duì)于可多次變更的數(shù)據(jù)顯得非常有用。例如前面提到的淘寶分布式訂閱框架所提供的Future式接口虽风,它允許多次調(diào)用waitNext()方法(相當(dāng)于Future.get())棒口,每次調(diào)用時(shí)是否阻塞取決于在上次調(diào)用后是否又有數(shù)據(jù)發(fā)布寄月,如果尚無更新,則阻塞直到下一次的數(shù)據(jù)發(fā)布无牵。這樣設(shè)計(jì)的好處是漾肮,接口的使用者可以在其任何合適的時(shí)機(jī),或者直接簡(jiǎn)單的在獨(dú)立的線程中通過一個(gè)無限循環(huán)響應(yīng)訂閱數(shù)據(jù)的變化茎毁,同時(shí)還可兼顧其它定時(shí)任務(wù)克懊,甚至同時(shí)等待多個(gè)Future。簡(jiǎn)化的例子如下:
for (;;) {
schedule = getNextScheduledTaskTime();
while(schedule > now()) {
try {
data = subscription.waitNext(schedule - now());
processData(data);
} catch(Exception e) {...}
}
doScheduledTask();
}
【原文來自:http://www.cnblogs.com/uptownBoy/articles/1772483.html】