原文地址? 譯者:羅立樹??校對:方騰飛
并發(fā)編程是一個難題,但是一個強(qiáng)大而簡單的抽象可以顯著的簡化并發(fā)的編寫。出于這樣的考慮,Guava 定義了?ListenableFuture接口并繼承了JDK concurrent包下的Future?接口。
我們強(qiáng)烈地建議你在代碼中多使用ListenableFuture來代替JDK的?Future, 因?yàn)?#xff1a;
- 大多數(shù)Futures?方法中需要它。
- 轉(zhuǎn)到ListenableFuture?編程比較容易。
- Guava提供的通用公共類封裝了公共的操作方方法,不需要提供Future和ListenableFuture的擴(kuò)展方法。
接口
傳統(tǒng)JDK中的Future通過異步的方式計算返回結(jié)果:在多線程運(yùn)算中可能或者可能在沒有結(jié)束返回結(jié)果,Future是運(yùn)行中的多線程的一個引用句柄,確保在服務(wù)執(zhí)行返回一個Result。
ListenableFuture可以允許你注冊回調(diào)方法(callbacks),在運(yùn)算(多線程執(zhí)行)完成的時候進(jìn)行調(diào)用, ?或者在運(yùn)算(多線程執(zhí)行)完成后立即執(zhí)行。這樣簡單的改進(jìn),使得可以明顯的支持更多的操作,這樣的功能在JDK concurrent中的Future是不支持的。
ListenableFuture?中的基礎(chǔ)方法是addListener(Runnable, Executor), 該方法會在多線程運(yùn)算完的時候,指定的Runnable參數(shù)傳入的對象會被指定的Executor執(zhí)行。
添加回調(diào)(Callbacks)
多數(shù)用戶喜歡使用?Futures.addCallback(ListenableFuture<V>, FutureCallback<V>, Executor)的方式, 或者 另外一個版本version(譯者注:addCallback(ListenableFuture<V>?future,FutureCallback<? super V>?callback)),默認(rèn)是采用?MoreExecutors.sameThreadExecutor()線程池, 為了簡化使用,Callback采用輕量級的設(shè)計. ?FutureCallback<V>?中實(shí)現(xiàn)了兩個方法:
- onSuccess(V),在Future成功的時候執(zhí)行,根據(jù)Future結(jié)果來判斷。
- onFailure(Throwable),?在Future失敗的時候執(zhí)行,根據(jù)Future結(jié)果來判斷。
ListenableFuture的創(chuàng)建
對應(yīng)JDK中的?ExecutorService.submit(Callable)?提交多線程異步運(yùn)算的方式,Guava 提供了ListeningExecutorService?接口, 該接口返回?ListenableFuture?而相應(yīng)的?ExecutorService?返回普通的?Future。將?ExecutorService?轉(zhuǎn)為?ListeningExecutorService,可以使用MoreExecutors.listeningDecorator(ExecutorService)進(jìn)行裝飾。
| 01 | ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)); |
| 02 | ListenableFuture explosion = service.submit(new?Callable() { |
| 03 | ??public?Explosion call() { |
| 04 | ????return?pushBigRedButton(); |
| 07 | Futures.addCallback(explosion,?new?FutureCallback() { |
| 08 | ??// we want this handler to run immediately after we push the big red button! |
| 09 | ??public?void?onSuccess(Explosion explosion) { |
| 10 | ????walkAwayFrom(explosion); |
| 12 | ??public?void?onFailure(Throwable thrown) { |
| 13 | ????battleArchNemesis();?// escaped the explosion! |
另外, 假如你是從?FutureTask轉(zhuǎn)換而來的, Guava 提供ListenableFutureTask.create(Callable<V>)?和ListenableFutureTask.create(Runnable, V). 和 JDK不同的是,?ListenableFutureTask?不能隨意被繼承(譯者注:ListenableFutureTask中的done方法實(shí)現(xiàn)了調(diào)用listener的操作)。
假如你喜歡抽象的方式來設(shè)置future的值,而不是想實(shí)現(xiàn)接口中的方法,可以考慮繼承抽象類AbstractFuture<V>?或者直接使用?SettableFuture?。
假如你必須將其他API提供的Future轉(zhuǎn)換成?ListenableFuture,你沒有別的方法只能采用硬編碼的方式JdkFutureAdapters.listenInPoolThread(Future)?來將?Future?轉(zhuǎn)換成?ListenableFuture。盡可能地采用修改原生的代碼返回?ListenableFuture會更好一些。
Application
使用ListenableFuture?最重要的理由是它可以進(jìn)行一系列的復(fù)雜鏈?zhǔn)降漠惒讲僮鳌?/p>
| 1 | ListenableFuture rowKeyFuture = indexService.lookUp(query); |
| 2 | AsyncFunction<RowKey, QueryResult> queryFunction = |
| 3 | new?AsyncFunction<RowKey, QueryResult>() { |
| 4 | public?ListenableFuture apply(RowKey rowKey) { |
| 5 | return?dataService.read(rowKey); |
| 8 | ListenableFuture queryFuture = Futures.transform(rowKeyFuture, queryFunction, queryExecutor); |
其他更多的操作可以更加有效的支持而JDK中的Future是沒法支持的.
不同的操作可以在不同的Executors中執(zhí)行,單獨(dú)的ListenableFuture?可以有多個操作等待。
當(dāng)一個操作開始的時候其他的一些操作也會盡快開始執(zhí)行–“fan-out”–ListenableFuture?能夠滿足這樣的場景:促發(fā)所有的回調(diào)(callbacks)。反之更簡單的工作是,同樣可以滿足“fan-in”場景,促發(fā)ListenableFuture?獲取(get)計算結(jié)果,同時其它的Futures也會盡快執(zhí)行:可以參考?the implementation of?Futures.allAsList?。(譯者注:fan-in和fan-out是軟件設(shè)計的一個術(shù)語,可以參考這里:http://baike.baidu.com/view/388892.htm#1或者看這里的解析Design Principles: Fan-In vs Fan-Out,這里fan-out的實(shí)現(xiàn)就是封裝的ListenableFuture通過回調(diào),調(diào)用其它代碼片段。fan-in的意義是可以調(diào)用其它Future)
| 方法 | 描述 | 參考 |
| transform(ListenableFuture<A>, AsyncFunction<A, B>, Executor)* | 返回一個新的ListenableFuture?,該ListenableFuture?返回的result是由傳入的AsyncFunction?參數(shù)指派到傳入的?ListenableFuture中. | transform(ListenableFuture<A>, AsyncFunction<A, B>) |
| transform(ListenableFuture<A>, Function<A, B>, Executor) | 返回一個新的ListenableFuture?,該ListenableFuture?返回的result是由傳入的Function?參數(shù)指派到傳入的?ListenableFuture中. | transform(ListenableFuture<A>, Function<A, B>) |
| allAsList(Iterable<ListenableFuture<V>>) | 返回一個ListenableFuture?,該ListenableFuture?返回的result是一個List,List中的值是每個ListenableFuture的返回值,假如傳入的其中之一fails或者cancel,這個Future fails 或者canceled | allAsList(ListenableFuture<V>...) |
| successfulAsList(Iterable<ListenableFuture<V>>) | 返回一個ListenableFuture?,該Future的結(jié)果包含所有成功的Future,按照原來的順序,當(dāng)其中之一Failed或者cancel,則用null替代 | successfulAsList(ListenableFuture<V>...) |
AsyncFunction<A, B>?中提供一個方法ListenableFuture<B> apply(A input),它可以被用于異步變換值。
| 1 | List<ListenableFuture> queries; |
| 2 | // The queries go to all different data centers, but we want to wait until they're all done or failed. |
| 4 | ListenableFuture<List> successfulQueries = Futures.successfulAsList(queries); |
| 6 | Futures.addCallback(successfulQueries, callbackOnSuccessfulQueries); |
CheckedFuture
Guava也提供了?CheckedFuture<V, X extends Exception>?接口。CheckedFuture?是一個ListenableFuture?,其中包含了多個版本的get 方法,方法聲明拋出檢查異常.這樣使得創(chuàng)建一個在執(zhí)行邏輯中可以拋出異常的Future更加容易 。將?ListenableFuture?轉(zhuǎn)換成CheckedFuture,可以使用?Futures.makeChecked(ListenableFuture<V>, Function<Exception, X>)。
原創(chuàng)文章,轉(zhuǎn)載請注明:?轉(zhuǎn)載自并發(fā)編程網(wǎng) – ifeve.com本文鏈接地址:?google Guava包的ListenableFuture解析
from:?http://ifeve.com/google-guava-listenablefuture/?
總結(jié)
以上是生活随笔為你收集整理的google Guava包的ListenableFuture解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。