ListenableFuture顧名思義就是可以監聽的Future,它是對java原生Future的擴展增強。我們知道Future表示一個異步計算任務,當任務完成時可以得到計算結果。如果我們希望一旦計算完成就拿到結果展示給用戶或者做另外的計算,就必須使用另一個線程不斷的查詢計算狀態。這樣做,代碼復雜,而且效率低下。使用ListenableFuture Guava幫我們檢測Future是否完成了,如果完成就自動調用回調函數,這樣可以減少並發程序的復雜度。
ListenableFuture是一個接口,它從jdk的Future接口繼承,添加了void addListener(Runnable listener, Executor executor)
方法。
我們看下如何使用ListenableFuture。首先需要定義ListenableFuture的實例。
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); final ListenableFuture<Integer> listenableFuture = executorService.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { System.out.println("call execute.."); TimeUnit.SECONDS.sleep(1); return 7; } });
首先通過MoreExecutors類的靜態方法listeningDecorator方法初始化一個ListeningExecutorService的方法,然后使用此實例的submit方法即可初始化ListenableFuture對象。
我們上文中定義的ListenableFuture要做的工作,在Callable接口的實現類中定義,這里只是休眠了1秒鍾然后返回一個數字7.
有了ListenableFuture實例,有兩種方法可以執行此Future並執行Future完成之后的回調函數。
方法一:通過ListenableFuture的addListener方法
listenableFuture.addListener(new Runnable() { @Override public void run() { try { System.out.println("get listenable future's result " + listenableFuture.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }, executorService);
方法二:通過Futures的靜態方法addCallback給ListenableFuture添加回調函數
Futures.addCallback(listenableFuture, new FutureCallback<Integer>() { @Override public void onSuccess(Integer result) { System.out.println("get listenable future's result with callback " + result); } @Override public void onFailure(Throwable t) { t.printStackTrace(); } });
推薦使用第二種方法,因為第二種方法可以直接得到Future的返回值,或者處理錯誤情況。本質上第二種方法是通過調動第一種方法實現的,做了進一步的封裝。
另外ListenableFuture還有其他幾種內置實現:
- SettableFuture:不需要實現一個方法來計算返回值,而只需要返回一個固定值來做為返回值,可以通過程序設置此Future的返回值或者異常信息
- CheckedFuture: 這是一個繼承自ListenableFuture接口,他提供了checkedGet()方法,此方法在Future執行發生異常時,可以拋出指定類型的異常。