Gauva使用ListenableFuture介紹說明
一、ListenableFuture 介紹
并發(fā)是一個(gè)困難問題,但是通過強(qiáng)大和強(qiáng)大的抽象能夠顯著的簡化工作。為了簡化問題,Gauva使用ListenableFuture擴(kuò)展了JDK的Future接口,
**我們強(qiáng)烈建議你在你所有的代碼中使用ListenableFuture
代替Future
,**因?yàn)椋?/p>
- 大多數(shù)的
Future
方法需要它; - 這比以后更改為
ListenableFuture
更容易; - 實(shí)用方法的提供者不需要提供
Future
和ListenableFuture
方法的變體;
二、接口
傳統(tǒng)的Future
代表著異步計(jì)算的結(jié)果:一個(gè)計(jì)算可能也可能沒有完成生成結(jié)果。Future可以是一個(gè)程序計(jì)算的句柄,一個(gè)來自服務(wù)的承諾提供給我們一個(gè)結(jié)果。
ListenableFuture
允許你注冊(cè)一個(gè)回調(diào)函數(shù),一旦計(jì)算是完成或者計(jì)算是已經(jīng)完成,回調(diào)函數(shù)會(huì)立馬執(zhí)行。這個(gè)簡單的添加能有效的支持多種Future接口不支持的操作。
基礎(chǔ)的操作被ListenableFuture
添加是通過addListener(Runnable, Executor)
,它指定了當(dāng)Future
的計(jì)算完成之后,指定的Runnable
將會(huì)在Executor
中執(zhí)行。
三、添加回調(diào)函數(shù)
大多數(shù)用戶更喜歡使用Futures.addCallback(ListenableFuture, FutureCallback, Executor)
,一個(gè)FutueCallback
有兩個(gè)方法:
onSuccess(V)
如果future執(zhí)行成功,基于結(jié)果進(jìn)行執(zhí)行。onFailure(Throwable)
如果future執(zhí)行失敗,基于失敗進(jìn)行執(zhí)行。
四、創(chuàng)建
相對(duì)于JDKExecutorService.submit(Callable)
方法初始化一個(gè)異步的計(jì)算。Guava提供了一個(gè)ListeningExecutorService
接口,它能在任何ExecutorService
返回一個(gè)正常Future
的地方,返回一個(gè)ListenableFuture
。為了將ExecutorService
轉(zhuǎn)換成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);
或者,如果你從一個(gè)基于FutureTask
的API進(jìn)行轉(zhuǎn)換,Guava提供了ListenableFutureTask.create(Callable)
和ListenableFutureTask.create(Runnable, V)
。并不像JDK,ListenableFutureTask
并不意味著直接擴(kuò)展。
如果您更喜歡設(shè)置未來值的抽象而不是實(shí)現(xiàn)計(jì)算值的方法,請(qǐng)考慮擴(kuò)展 AbstractFuture<V>
或直接使用 SettableFuture
。
如果你必須將另一個(gè)API提供的Future轉(zhuǎn)換成ListenableFuture
,你沒有選擇除了使用重量級(jí)的JdkFutureAdapters.listenInPoolThread(Future)
,將Future轉(zhuǎn)化成ListenableFuture
。無論什么時(shí)候,只要有可能,都應(yīng)該修改源代碼去返回一個(gè)ListenableFuture
。
五、應(yīng)用
使用ListenableFuture
的重要原因是,它讓異步的鏈操作成為可能。
很多有效的其它操作使用ListenableFuture
是支持的,而單獨(dú)使用Future
是不支持的。不同的操作能夠被不同的Executor執(zhí)行,并且單個(gè) ListenableFuture 可以有多個(gè)等待它的操作。
當(dāng)多個(gè)操作應(yīng)該在另一個(gè)操作開始時(shí)立即開始時(shí)——“扇出”——ListenableFuture 才起作用:它觸發(fā)所有請(qǐng)求的回調(diào)。通過稍微多一點(diǎn)的工作,我們能“扇入”,或觸發(fā)ListenableFuture
進(jìn)行計(jì)算只要若干個(gè)其它的Future執(zhí)行完(看:Futures.allAsList
)。
方法 | 描述 | 延伸 |
---|---|---|
Futures.transformAsync(ListenableFuture, AsyncFunction, Executor) | 返回一個(gè)新的ListenableFuture ,它的結(jié)果是應(yīng)用AsyncFunction。AsyncFunction是對(duì)ListenableFuture結(jié)果的加工 | |
Futures.transform(ListenableFuture, Function, Executor) | 返回一個(gè)新的ListenableFuture ,它的結(jié)果是應(yīng)用Function。Function是對(duì)ListenableFuture結(jié)果的加工 | |
Futures.allAsList(Iterable<ListenableFuture<V>>) | 返回一個(gè)ListenableFuture ,它的值是一個(gè)list包含了每一個(gè)輸入輸入future的值。如果任何的future失敗或取消,這個(gè)future也失敗或取消。 | |
Futures.successfulAsList(Iterable<ListenableFuture>) | 返回一個(gè)ListenableFuture ,它的值是一個(gè)list包含了每一個(gè)輸入輸入future的值。如果相對(duì)應(yīng)的future失敗或取消,將用null代替。 |
一個(gè)AsyncFunction
提供了一個(gè)方法ListenableFuture<B> apply(A a)
。它用于異步傳輸一個(gè)值。
六、避免內(nèi)嵌的Future
ListenableFuture<ListenableFuture<String>> nestedFuture = executorService.submit(() -> otherExecutorService.submit(() -> callDemo()));
上面的代碼是不正確的, 因?yàn)槿绻獠縁uture的取消與外部Future的完成競爭,則該取消不會(huì)傳播到內(nèi)部Future。 使用 get() 或偵 聽器檢查其他Future的失敗也是一個(gè)常見錯(cuò)誤,但除非特別注意,否則從 otherCallable 拋出的異常將被抑制。
為了避免這種情況,Guava 的所有Future處理方法(以及一些來自 JDK)都有 *Async 版本,可以安全地解開這個(gè)嵌套:
Futures.transformAsync(ListenableFuture, AsyncFunction, Executor)
ExecutorService.submit(Callable)
Futures.submitAsync(AsyncCallable, Executor)
到此這篇關(guān)于Gauva使用ListenableFuture介紹說明的文章就介紹到這了,更多相關(guān)Gauva ListenableFuture內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot基于Redisson實(shí)現(xiàn)Redis分布式可重入鎖源碼解析
這篇文章主要介紹了Springboot基于Redisson實(shí)現(xiàn)Redis分布式可重入鎖,本文通過案例源碼分析給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03SpringBoot的配置文件application.yml及加載順序詳解
這篇文章主要介紹了SpringBoot的配置文件application.yml及加載順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Springboot實(shí)現(xiàn)自定義錯(cuò)誤頁面的方法(錯(cuò)誤處理機(jī)制)
這篇文章主要介紹了Springboot實(shí)現(xiàn)自定義錯(cuò)誤頁面的方法(錯(cuò)誤處理機(jī)制),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01springboot?vue測(cè)試平臺(tái)接口定義前后端新增功能實(shí)現(xiàn)
這篇文章主要介紹了springboot?vue測(cè)試平臺(tái)接口定義前后端新增功能實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05通過java備份恢復(fù)mysql數(shù)據(jù)庫的實(shí)現(xiàn)代碼
這篇文章主要介紹了如何通過java備份恢復(fù)mysql數(shù)據(jù)庫,其實(shí)一般情況下通過bat或sh就可以,這里主要是介紹了java的實(shí)現(xiàn)思路,喜歡的朋友可以參考下2013-09-09