Java CompletableFuture

Future(接口)

Future是Java 5添加的類,用來描述一個異步計算的結果.java

特色

  1. 對於結果的獲取不是很方便,只能經過阻塞或者輪詢的方式獲得任務的結果。不能及時地獲得計算結果.
  2. 一旦一個運算操做已經完成,這個運算操做就不能被取消。

方法

boolean cancel (boolean mayInterruptIfRunning) //取消執行此任務編程

  • a)噹噹前任務已完成,已被取消,或由於一些其它緣由不能被取消,這個操做會失敗.
  • b)若調用該方法時,任務還未開始,則當前任務應該永遠不運行.
  • c) mayInterruptIfRunning爲true時表示容許中斷正在運行的任務.
  • d)若此方法被調用,則隨後調用的 isCancled (), isDone() 將始終返回true.

boolean isCancled () 若此任務在正常完成前被取消則返回true.app

boolean isDone() //當前任務是否完成
可能的狀況有:正常完成,異常,取消執行.在這些狀況下將會返回true.dom

V get() throws InterruptedException,ExecutionException //若是必要的話,等待計算完成,並返回其結果異步

  • a)返回計算的結果

V get(long timeout,TimeUnit unit) throws InterruptedException,ExecutionException,TimeoutException //若是必要的話,等待計算完成,並返回其結果函數式編程

  • a)timeout:最長等待時間 timeunit:超時的時間單位
  • b)若成功,返回計算結果

CompletionStage(接口)及CompletableFuture

CompletableFuture實現了Future及CompletionStage接口,是Java 8 新增的一個類.提供了很是強大的Future的擴展功能,能夠幫助咱們簡化異步編程的複雜性,提供了函數式編程的能力,能夠經過回調的方式處理計算結果,而且提供了轉換和組合CompletableFuture的方法。異步編程

特色

  1. 一個Future能夠被明確的完成(設置它的值或狀態);而且看成爲一個CompletionStage使用時能夠支持依賴函數和當任務完成時觸發相應動做的使用.函數

  2. 當兩個或多個線程試圖 complete, completeExceptionally或 cancel 一個CompletableFuture時,只有一個線程能成功。線程

  3. CompletableFuture實現了CompletionStage接口方法中的如下策略:debug

  • a)對全部非異步方法的執行,能夠由執行當前的CompletableStage的線程執行,也能夠由完成方法的其它調用者執行.
  • b) 全部不顯式指示參數Executor都使用ForkJoinPool.commonPool()(除非它不支持至少二個並行級別的運算,在這種狀況下,將會建立一個新的線程去執行當前任務).爲了簡化監控,debug,追蹤,全部生成的異步任務都標記爲CompletableFuture.AsynchronousCompletionTask.接口的一個實例.
  • c)全部的CompletionStage方法都是獨立於其它共公有方法的.因此一個方法的行爲不影響子類中其它重寫方法.
  1. CompletableFuture還實現了Future的如下策略:
  • a)由於不像FutureTask直接操做計算從而完成任務,cancel()看作另外一種異常完成的表現形式.因此,cancel()方法與 completeExceptionally(new CancellationException())效果相同.方法 isCompletedExceptionally()能夠用來肯定一個CompletableFuture是否以任何異常形式完成.

內部嵌套類

static interface 	CompletableFuture.AsynchronousCompletionTask
//一個標識接口,用於標識由異步方法產生的異步任務,可能用於監控,debug,追蹤異步活動.

方法

注意:在下文中: 不以Async結尾,意味着Action使用相同的線程執行,而Async可能會使用其它的線程去執行(若是使用相同的線程池,也可能會被同一個線程選中執行)。

  1. 不以Async結尾,意味着Action使用相同的線程執行.
  2. 以Async結尾而且沒有指定Executor的方法會使用ForkJoinPool.commonPool()做爲它的線程池執行異步代碼。
  3. 若參數中有Executor則使用參數中指定的executor線程池實現..
  4. 以Runnable函數式接口類型爲參數,因此CompletableFuture的計算結果爲空。
  5. 以Supplier< U >函數式接口類型爲參數,CompletableFuture的計算結果類型爲U。由於方法的參數類型爲函數式接口,因此可使用lambda表達式實現異步任務.(簡化代碼,常用)

能夠根據方法的參數的類型來加速你的記憶。Runnable類型的參數會忽略計算的結果,Consumer是純消費計算結果,BiConsumer會組合另一個CompletionStage純消費,Function會對計算結果作轉換,BiFunction會組合另一個CompletionStage的計算結果作轉換。

構造方法

public CompletableFuture() //建立一個不完整的CompletableFuture

建立CompletableFuture對象

a)CompletableFuture.completedFuture(U value)是一個靜態輔助方法,用來返回一個已經計算好的CompletableFuture。

public static <U> CompletableFuture<U> completedFuture(U value)

b)爲異步執行的代碼建立CompletableFuture建立對象的靜態方法

public static CompletableFuture<Void> 	runAsync(Runnable runnable)
public static CompletableFuture<Void> 	runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> 	supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> 	supplyAsync(Supplier<U> supplier, Executor executor)

計算結果完成時的處理

(1). 第一組

當CompletableFuture的計算結果完成,或者拋出異常的時候,咱們能夠執行特定的Action。主要是下面的方法:

public CompletableFuture<T> 	whenComplete(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> 	whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> 	whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
public CompletableFuture<T>     exceptionally(Function<Throwable,? extends T> fn)
  • a)Action的類型是BiConsumer<? super T,? super Throwable>,它能夠處理正常的計算結果,或者異常狀況。
  • b)這幾個方法都會返回CompletableFuture,當Action執行完畢它的結果後返回原始的CompletableFuture的計算結果或者返回異常。
  • c)exceptionally方法返回一個新的CompletableFuture,當原始的CompletableFuture拋出異常的時候,就會觸發這個CompletableFuture的計算,調用function計算值,不然若是原始的CompletableFuture正常計算完後,這個新的CompletableFuture也計算完成,它的值和原始的CompletableFuture的計算的值相同。也就是這個exceptionally方法用來處理異常的狀況。

(2). 第二組

這一組方法雖然也返回CompletableFuture對象,可是對象的值和原來的CompletableFuture計算的值不一樣,會生成新的計算結果.當原先的CompletableFuture的值計算完成或者拋出異常的時候,會觸發這個CompletableFuture對象的計算,結果由BiFunction參數計算而得。所以這組方法兼有whenComplete和轉換(thenAply)的兩個功能。

public <U> CompletableFuture<U> 	handle(BiFunction<? super T,Throwable,? extends U> fn)
public <U> CompletableFuture<U> 	handleAsync(BiFunction<? super T,Throwable,? extends U> fn)
public <U> CompletableFuture<U> 	handleAsync(BiFunction<? super T,Throwable,? extends U> fn, Executor executor)

轉換

轉換時沒必要由於等待一個計算完成而阻塞着調用線程(好比Future的get()方法),而是告訴CompletableFuture當計算完成的時候請執行某個function。並且咱們還能夠將這些操做串聯起來,或者將CompletableFuture組合起來。

public <U> CompletableFuture<U> 	thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> 	thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> 	thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)
  • a)功能:當原來的CompletableFuture計算完後,將結果傳遞給函數fn,將fn的結果做爲新的CompletableFuture計算結果。所以它的功能至關於將CompletableFuture< T >轉換成CompletableFuture< U >。
  • b):這些轉換並非立刻執行的,也不會阻塞,而是在前一個stage完成後繼續執行。
  • c)與handle的區別在於:handle方法會處理正常計算值和異常,所以它能夠屏蔽異常,避免異常繼續拋出。而thenApply方法只是用來處理正常值,所以一旦有異常就會拋出。

純消費(執行action)

public CompletableFuture<Void> 	thenAccept(Consumer<? super T> action)
public CompletableFuture<Void> 	thenAcceptAsync(Consumer<? super T> action)
public CompletableFuture<Void> 	thenAcceptAsync(Consumer<? super T> action, Executor executor)

功能:只對結果執行Action,而不返回新的計算值.

public <U> CompletableFuture<Void> 	thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action)
public <U> CompletableFuture<Void> 	thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action)
public <U> CompletableFuture<Void> 	thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T,? super U> action, Executor executor)
public     CompletableFuture<Void> 	runAfterBoth(CompletionStage<?> other,  Runnable action)
  • a)thenAcceptBoth方法功能:當二個CompletionStage都正常完成計算的時候,就會執行提供的action,它們用來組合另一個異步的結果.
  • b)runAfterBoth是當兩個CompletionStage都正常完成計算的時候,執行一個Runnable,這個Runnable並不使用計算的結果。

組合

(1):第一組

public <U> CompletableFuture<U> 	thenCompose(Function<? super T,? extends CompletionStage<U>> fn)
public <U> CompletableFuture<U> 	thenComposeAsync(Function<? super T,? extends CompletionStage<U>> fn)
public <U> CompletableFuture<U> 	thenComposeAsync(Function<? super T,? extends CompletionStage<U>> fn, Executor executor)
  • a)功能:這一組方法接受一個Function做爲參數,這個Function的輸入是當前的CompletableFuture的計算值,返回結果將是一個新的CompletableFuture,這個新的CompletableFuture會組合原來的CompletableFuture和函數返回的CompletableFuture。
  • b)thenCompose返回的對象並不一是函數fn返回的對象,若是原來的CompletableFuture尚未計算出來,它就會生成一個新的組合後的CompletableFuture。

(2):第二組

public <U,V> CompletableFuture<V> 	thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> 	thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn)
public <U,V> CompletableFuture<V> 	thenCombineAsync(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn, Executor executor)
  • a)用來複合另一個CompletionStage的結果.
  • b)兩個CompletionStage是並行執行的,它們之間並無前後依賴順序,other並不會等待先前的CompletableFuture執行完畢後再執行。

Either

public CompletableFuture<Void> 	acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> 	acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action)
public CompletableFuture<Void> 	acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor)
public <U> CompletableFuture<U> 	applyToEither(CompletionStage<? extends T> other, Function<? super T,U> fn)
public <U> CompletableFuture<U> 	applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn)
public <U> CompletableFuture<U> 	applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn, Executor executor)
  • a)acceptEither方法是當任意一個CompletionStage完成的時候,action這個消費者就會被執行。這個方法返回CompletableFuture< Void >
  • b)applyToEither方法是當任意一個CompletionStage完成的時候,fn會被執行,它的返回值會看成新的CompletableFuture< U >的計算結果。

例子:可能輸出100,也可能輸出200

Random rand = new Random();
CompletableFuture< Integer > future = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(10000 + rand.nextInt(1000));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return 100;
});
CompletableFuture< Integer > future2 = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(10000 + rand.nextInt(1000));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return 200;
});
CompletableFuture<String> f =  future.applyToEither(future2,i -> i.toString());

輔助方法allOf()和anyOf()

public static CompletableFuture<Void> 	    allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> 	anyOf(CompletableFuture<?>... cfs)
  • a)這兩個方法用來組合多個CompletableFuture。
  • b)allOf方法是當全部的CompletableFuture都執行完後執行計算。
  • c)anyOf方法是當任意一個CompletableFuture執行完後就會執行計算,計算的結果相同。

anyOf()與applyToEither()的區別:

  • a)anyOf()能夠接受任意多的CompletableFuture;但applyToEither()只能判斷二個VompletableFuture.
  • b)anyOf()返回的計算結果是衆多CompletableFuture參數中其中一個CompletableFuture的計算結果.;applyToEither返回值的結果是要通過fn處理的.
  • c):還有靜態方法的區別,線程池的選擇等.
相關文章
相關標籤/搜索