1. 程式人生 > >CompletableFuture基本用法

CompletableFuture基本用法

無需 lock 函數式 數據顯示 func 分享圖片 cti 多線程 函數式編程

首先是https://www.jianshu.com/p/4897ccdcb278這個帖子,代碼差不多貼了跑了,主要是completableFuture的一些方法的用法

然後是來自https://www.cnblogs.com/cjsblog/p/9267163.html的帖子

https://www.cnblogs.com/cjsblog/p/9267163.html

異步計算

  • 所謂異步調用其實就是實現一個可無需等待被調用函數的返回值而讓操作繼續運行的方法。在 Java 語言中,簡單的講就是另啟一個線程來完成調用中的部分計算,使調用繼續運行或返回,而不需要等待計算結果。但調用者仍需要取線程的計算結果。

  • JDK5新增了Future接口,用於描述一個異步計算的結果。雖然 Future 以及相關使用方法提供了異步執行任務的能力,但是對於結果的獲取卻是很不方便,只能通過阻塞或者輪詢的方式得到任務的結果。阻塞的方式顯然和我們的異步編程的初衷相違背,輪詢的方式又會耗費無謂的 CPU 資源,而且也不能及時地得到計算結果。

  • 以前我們獲取一個異步任務的結果可能是這樣寫的

  技術分享圖片

Future 接口的局限性

Future接口可以構建異步應用,但依然有其局限性。它很難直接表述多個Future 結果之間的依賴性。實際開發中,我們經常需要達成以下目的:

  1. 將多個異步計算的結果合並成一個

  2. 等待Future集合中的所有任務都完成

  3. Future完成事件(即,任務完成以後觸發執行動作)

  4. 。。。

函數式編程

技術分享圖片

CompletionStage

  • CompletionStage代表異步計算過程中的某一個階段,一個階段完成以後可能會觸發另外一個階段

  • 一個階段的計算執行可以是一個Function,Consumer或者Runnable。比如:stage.thenApply(x -> square(x)).thenAccept(x -> System.out.print(x)).thenRun(() -> System.out.println())

  • 一個階段的執行可能是被單個階段的完成觸發,也可能是由多個階段一起觸發

CompletableFuture

  • 在Java8中,CompletableFuture提供了非常強大的Future的擴展功能,可以幫助我們簡化異步編程的復雜性,並且提供了函數式編程的能力,可以通過回調的方式處理計算結果,也提供了轉換和組合 CompletableFuture 的方法。
  • 它可能代表一個明確完成的Future,也有可能代表一個完成階段( CompletionStage ),它支持在計算完成以後觸發一些函數或執行某些動作。
  • 它實現了Future和CompletionStage接口

  技術分享圖片

CompletableFuture基本用法

創建CompletableFuture

技術分享圖片

thenApply

技術分享圖片

當前階段正常完成以後執行,而且當前階段的執行的結果會作為下一階段的輸入參數。thenApplyAsync默認是異步執行的。這裏所謂的異步指的是不在當前線程內執行。

thenApply相當於回調函數(callback)

技術分享圖片


技術分享圖片

thenAccept與thenRun

技術分享圖片

  • 可以看到,thenAccept和thenRun都是無返回值的。如果說thenApply是不停的輸入輸出的進行生產,那麽thenAccept和thenRun就是在進行消耗。它們是整個計算的最後兩個階段。
  • 同樣是執行指定的動作,同樣是消耗,二者也有區別:

    • thenAccept接收上一階段的輸出作為本階段的輸入   

    • thenRun根本不關心前一階段的輸出,根本不不關心前一階段的計算結果,因為它不需要輸入參數

thenCombine整合兩個計算結果

技術分享圖片

例如,此階段與其它階段一起完成,進而觸發下一階段:

技術分享圖片

whenComplete

技術分享圖片

最後,舉個栗子:

技術分享圖片

事實上,如果每個操作都很簡單的話(比如:上面的例子中按照id去查)沒有必要用這種多線程異步的方式,因為創建線程還需要時間,還不如直接同步執行來得快。

事實證明,只有當每個操作很復雜需要花費相對很長的時間(比如,調用多個其它的系統的接口;比如,商品詳情頁面這種需要從多個系統中查數據顯示的)的時候用CompletableFuture才合適,不然區別真的不大,還不如順序同步執行。

CompletableFuture基本用法