「用 CompletableFuture 處理異步超時」 閱讀總結

譯文:http://www.importnew.com/16149.htmlhtml

原文:http://www.javacodegeeks.com/2014/12/asynchronous-timeouts-with-completablefuture.htmljava

總結

爲何要引入 CompletableFuture

  • Future.get() 方法會阻塞線程,一直阻塞,直到其所對應的任務完成或由於異常退出。在不恰當的地方調用此方法會由於線程阻塞而下降系統響應度。就像文中提到的。
  • Future.get(long, TimeUnit) 能夠必定的時間內超時退出,而不會像前一個方法那樣一直阻塞線程。可是這對系統響應性的改進是治標不治本。
  • Java 8 引入了 CompletableFuture,可用經過 CompletableFuture<Void> thenAccept(Consumer<? super T> action) 方法異步觸發 send(Response) 方法。這時 serve() 方法會很快結束。而當 responseFuture 所對應的任務完成時,send(Response) 方法便會被調用,其執行線程同 responseFuture 所對應的任務的執行線程相同。
  • 對於上一點,有人會問,何須這麼麻煩?直接在 responseFuture 所對應任務 (Runnable or Callable) 裏面調用 send(Response) 方法。各類在實際工做中可能會遇到的問題暫且不說。只說兩點:
    1. responseFuture 所對應任務是不可修改的,好比調用自第三方模塊
    2. 即使代碼可修改,但在 responseFuture 所對應的任務中去調用 send(Response) 方法代表的含義是後者的功能從屬於前者。這可能從業務角度上看是不合理的。即在本例中,responseFuture 所對應的任務和 send(Response) 方法在業務角度講是屬於同一級的。違反這一點會對代碼可讀性和可維護性不利。

thenAcceptthenAcceptAsync

  • thenAccept(Consumer<? super T> action) 這個方法的命名採用了相似 Promise 的命名風格。若是把這個方法命名爲 addListener 會更容易理解,可是命名爲 addListener 不能體現出 thenAccept 能返回 CompletableFuture 從而造成鏈式調用的特色。
  • CompletableFuture 還有一個方法 thenAcceptAsync(Consumer<? super T> action, Executor executor),能夠爲任務指定線程池,從而隔離不一樣任務的執行線程,避免相互影響。(吐槽一下,CompletableFuture 定義的方法實在太多了)

異常處理

  • 再使用 thenAccept 方法調用 send 方法實現了異步編程,帶來了好處,但同時也帶來了不少問題。第一個問題即是異常的處理。在使用 Java 寫併發程序的時候要注意異常處理,這是一個從 Java 1.4 開始就須要注意的問題。有經驗的開發人員都知道 Java 的 Thread 有兩個和異常處理相關的方法,分別是 setDefaultUncaughtExceptionHandlersetUncaughtExceptionHandler。前者是靜態方法。這兩個方法是用來設置異常處理策略的。固然,一個更簡單的方法是在 send 裏捕獲和處理全部異常。若是你和你的公司容許大量無聊的重複代碼出現的話,這麼作是沒有問題的。
  • 從 Java 8 開始,在併發編程中處理異常,除了上面提到的本身寫 try catch 和使用 UncaughtExceptionHandler 這兩種方法外,對於本例來講,還能夠經過 CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn) 方法來處理異常。
  • exceptionally() 方法中的 Function 是用來處理 responseFuture 所對應任務拋出的異常
  • 若是出現異常,Function 的返回值將做爲 thenAccept 方法的 Consumer 入參。在本例中就是 null

超時異常

  • 解決了異常問題以後另外一個須要解決的問題是如何實現超時異常
  • 經過 CompletableFuture 實現超時異常場景的方法是經過使用 CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)。這個方法的意思是 this CompletionStage 或 other CompletionStage 誰先完成,其結果就會做爲 Consumer<? super T> action 的入參。而後經過實現一個超時的 CompletionStage
  • 接下來就是對代碼可讀性的一些改進,用了 CompletableFuture 另外一些方法。

最後

CompletableFuture 是一個提供了多種複雜異步功能的類。有時間最好能瞭解一下這個類的源代碼編程

相關文章
相關標籤/搜索