Gauva使用ListenableFuture介紹說明
一、ListenableFuture 介紹
並發是一個困難問題,但是通過強大和強大的抽象能夠顯著的簡化工作。為瞭簡化問題,Gauva使用ListenableFuture擴展瞭JDK的Future接口,
**我們強烈建議你在你所有的代碼中使用ListenableFuture
代替Future
,**因為:
- 大多數的
Future
方法需要它; - 這比以後更改為
ListenableFuture
更容易; - 實用方法的提供者不需要提供
Future
和ListenableFuture
方法的變體;
二、接口
傳統的Future
代表著異步計算的結果:一個計算可能也可能沒有完成生成結果。Future可以是一個程序計算的句柄,一個來自服務的承諾提供給我們一個結果。
ListenableFuture
允許你註冊一個回調函數,一旦計算是完成或者計算是已經完成,回調函數會立馬執行。這個簡單的添加能有效的支持多種Future接口不支持的操作。
基礎的操作被ListenableFuture
添加是通過addListener(Runnable, Executor)
,它指定瞭當Future
的計算完成之後,指定的Runnable
將會在Executor
中執行。
三、添加回調函數
大多數用戶更喜歡使用Futures.addCallback(ListenableFuture, FutureCallback, Executor)
,一個FutueCallback
有兩個方法:
onSuccess(V)
如果future執行成功,基於結果進行執行。onFailure(Throwable)
如果future執行失敗,基於失敗進行執行。
四、創建
相對於JDKExecutorService.submit(Callable)
方法初始化一個異步的計算。Guava提供瞭一個ListeningExecutorService
接口,它能在任何ExecutorService
返回一個正常Future
的地方,返回一個ListenableFuture
。為瞭將ExecutorService
轉換成ListeningExecutorService
,僅需要使用MoreExecutors.listeningDecorator(executorService)
:
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors())); ListenableFuture<String> listenableFuture = service.submit(() -> callDemo()); Futures.addCallback(listenableFuture, new FutureCallback<String>() { @Override public void onSuccess(String result) { System.out.println("Run Ok : " + result); // service.shutdown(); } @Override public void onFailure(Throwable t) { System.out.println("Run Fail: " + t); } }, service);
或者,如果你從一個基於FutureTask
的API進行轉換,Guava提供瞭ListenableFutureTask.create(Callable)
和ListenableFutureTask.create(Runnable, V)
。並不像JDK,ListenableFutureTask
並不意味著直接擴展。
如果您更喜歡設置未來值的抽象而不是實現計算值的方法,請考慮擴展 AbstractFuture<V>
或直接使用 SettableFuture
。
如果你必須將另一個API提供的Future轉換成ListenableFuture
,你沒有選擇除瞭使用重量級的JdkFutureAdapters.listenInPoolThread(Future)
,將Future轉化成ListenableFuture
。無論什麼時候,隻要有可能,都應該修改源代碼去返回一個ListenableFuture
。
五、應用
使用ListenableFuture
的重要原因是,它讓異步的鏈操作成為可能。
很多有效的其它操作使用ListenableFuture
是支持的,而單獨使用Future
是不支持的。不同的操作能夠被不同的Executor執行,並且單個 ListenableFuture 可以有多個等待它的操作。
當多個操作應該在另一個操作開始時立即開始時——“扇出”——ListenableFuture 才起作用:它觸發所有請求的回調。通過稍微多一點的工作,我們能“扇入”,或觸發ListenableFuture
進行計算隻要若幹個其它的Future執行完(看:Futures.allAsList
)。
方法 | 描述 | 延伸 |
---|---|---|
Futures.transformAsync(ListenableFuture, AsyncFunction, Executor) |
返回一個新的ListenableFuture ,它的結果是應用AsyncFunction。AsyncFunction是對ListenableFuture結果的加工 |
|
Futures.transform(ListenableFuture, Function, Executor) |
返回一個新的ListenableFuture ,它的結果是應用Function。Function是對ListenableFuture結果的加工 |
|
Futures.allAsList(Iterable<ListenableFuture<V>>) |
返回一個ListenableFuture ,它的值是一個list包含瞭每一個輸入輸入future的值。如果任何的future失敗或取消,這個future也失敗或取消。 |
|
Futures.successfulAsList(Iterable<ListenableFuture>) |
返回一個ListenableFuture ,它的值是一個list包含瞭每一個輸入輸入future的值。如果相對應的future失敗或取消,將用null代替。 |
一個AsyncFunction
提供瞭一個方法ListenableFuture<B> apply(A a)
。它用於異步傳輸一個值。
六、避免內嵌的Future
ListenableFuture<ListenableFuture<String>> nestedFuture = executorService.submit(() -> otherExecutorService.submit(() -> callDemo()));
上面的代碼是不正確的, 因為如果外部Future的取消與外部Future的完成競爭,則該取消不會傳播到內部Future。 使用 get() 或偵 聽器檢查其他Future的失敗也是一個常見錯誤,但除非特別註意,否則從 otherCallable 拋出的異常將被抑制。
為瞭避免這種情況,Guava 的所有Future處理方法(以及一些來自 JDK)都有 *Async 版本,可以安全地解開這個嵌套:
Futures.transformAsync(ListenableFuture, AsyncFunction, Executor)
ExecutorService.submit(Callable)
Futures.submitAsync(AsyncCallable, Executor)
到此這篇關於Gauva使用ListenableFuture介紹說明的文章就介紹到這瞭,更多相關Gauva ListenableFuture內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- java中ExecutorService創建方法總結
- Java多線程教程之如何利用Future實現攜帶結果的任務
- Java並發編程必備之Future機制
- Java多線程 Callable、Future 和FutureTask
- 解析Java異步之call future