1. 引子
ListenableFuture顧名思義就是能夠監聽的Future,它是對java原生Future的擴展加強。咱們知道Future表示一個異步計算任務,當任務完成時能夠獲得計算結果。若是咱們但願一旦計算完成就拿到結果展現給用戶或者作另外的計算,就必須使用另外一個線程不斷的查詢計算狀態。這樣作,代碼複雜,並且效率低下。使用ListenableFuture Guava幫咱們檢測Future是否完成了,若是完成就自動調用回調函數,這樣能夠減小併發程序的複雜度。java
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; } });
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對象。ide
咱們上文中定義的ListenableFuture要作的工做,在Callable接口的實現類中定義,這裏只是休眠了1秒鐘而後返回一個數字7.函數
有了ListenableFuture實例,有兩種方法能夠執行此Future並執行Future完成以後的回調函數。spa
方法一:經過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);
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添加回調函數code
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(); } });
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執行發生異常時,能夠拋出指定類型的異常。
參考:
http://outofmemory.cn/java/guava/concurrent/ListenableFuture