所謂異步調用其實就是實現一個可無需等待被調用函數的返回值而讓操做繼續運行的方法。在 Java 語言中,簡單的講就是另啓一個線程來完成調用中的部分計算,使調用繼續運行或返回,而不須要等待計算結果。但調用者仍須要取線程的計算結果。編程
JDK5新增了Future接口,用於描述一個異步計算的結果。雖然 Future 以及相關使用方法提供了異步執行任務的能力,可是對於結果的獲取倒是很不方便,只能經過阻塞或者輪詢的方式獲得任務的結果。阻塞的方式顯然和咱們的異步編程的初衷相違背,輪詢的方式又會耗費無謂的 CPU 資源,並且也不能及時地獲得計算結果。多線程
Future接口能夠構建異步應用,但依然有其侷限性。它很難直接表述多個Future 結果之間的依賴性。實際開發中,咱們常常須要達成如下目的:異步
將多個異步計算的結果合併成一個函數式編程
等待Future集合中的全部任務都完成異步編程
Future完成事件(即,任務完成之後觸發執行動做)函數
CompletionStage表明異步計算過程當中的某一個階段,一個階段完成之後可能會觸發另一個階段spa
一個階段的計算執行能夠是一個Function,Consumer或者Runnable。好比:stage.thenApply(x -> square(x)).thenAccept(x -> System.out.print(x)).thenRun(() -> System.out.println())線程
一個階段的執行多是被單個階段的完成觸發,也多是由多個階段一塊兒觸發3d
當前階段正常完成之後執行,並且當前階段的執行的結果會做爲下一階段的輸入參數。thenApplyAsync默認是異步執行的。這裏所謂的異步指的是不在當前線程內執行。blog
一樣是執行指定的動做,一樣是消耗,兩者也有區別:
thenAccept接收上一階段的輸出做爲本階段的輸入
例如,此階段與其它階段一塊兒完成,進而觸發下一階段:
事實上,若是每一個操做都很簡單的話(好比:上面的例子中按照id去查)沒有必要用這種多線程異步的方式,由於建立線程還須要時間,還不如直接同步執行來得快。
事實證實,只有當每一個操做很複雜須要花費相對很長的時間(好比,調用多個其它的系統的接口;好比,商品詳情頁面這種須要從多個系統中查數據顯示的)的時候用CompletableFuture才合適,否則區別真的不大,還不如順序同步執行。