Java8 加強的Future:CompletableFuture(筆記)

     CompletableFuture是Java8新增的一個超大型工具類,爲何說她大呢?由於一方面它實現了Future接口,更重要的是,它實現了CompletionStage接口.這個接口也是Java8新增長的,而CompletionStage擁有多達約40種方法,

	* 完成了通知我
	* 異步執行任務

經過CompletableFuture提供進一步封裝,咱們很容易實現Future模式那樣的異步調用,例如:
public static Integer cale(Integer para) {
    try {
        Thread.sleep(1000);

    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return para * para;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {

    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> cale(50));
    System.out.println(future.get());
}

上述代碼中CompletableFuture.supplyAsync()方法構造了一個CompletableFuture實例,在supplyAsync()函數中,他會在一個新的線程中,執行傳入的參數.在這裏,,他會執行calc()方法,而calc()方法的執行多是比較慢的,可是不影響CompletableFuture實例的構造速度,所以supplyAsync()會當即返回,他返回的CompletableFuture對象實例就能夠做爲此次調用的契約,在未來任何場合,用於得到最終的計算結果.
在CompletableFuture中,相似的工廠方法有如下幾個:
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) 
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                   Executor executor)
public static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable,
                                               Executor executor)

     其中supplyAsync()方法用於那些須要返回值的場景,好比計算某個數據,而runAsync()方法用於沒有返回值的場景,好比,僅僅是簡單地執行某一個異步動做.
     在這兩對方法中,都有一個方法能夠接手一個Executor參數,這使咱們可讓Supplier<U>或者Runnable在指定的線程池工做,若是不指定,則在默認的系統公共的ForkJoinPool.common線程池中執行.

	* 流式調用

在前文中我已經簡單的提到,CompletionStage的約40個接口爲函數式編程作準備的,在這裏,就讓咱們看一下,若是使用這些接口進行函數式的流式API調用:
CompletableFuture<Void> future = CompletableFuture
        .supplyAsync(() -> cale(50))
        .thenApply(i -> Integer.toString(i))
        .thenApply(str -> "\"" + str + "\"")
        .thenAccept(System.out::println);
future.get();

     上述代碼中,使用supplyAsync()函數執行了一個異步任務,接着連續使用流式調用對任務處理結果進行在加工,直到最後的結果輸出:

	* CompletableFuture中的異常處理

CompletableFuture<Void> future = CompletableFuture
        .supplyAsync(() -> cale(50))
        .exceptionally(ex -> {
            System.out.println("ex.toString() = " + ex.toString());
            return 0;
        })
        .thenApply(i -> Integer.toString(i))
        .thenApply(str -> "\"" + str + "\"")
        .thenAccept(System.out::println);
future.get();


	* 組合多個CompletableFuture

CompletableFuture還容許你將多個CompletableFuture進行組合,一種方法是使用thenCompose(),它的簽名以下:
public <U> CompletableFuture<U> thenCompose(
    Function<? super T, ? extends CompletionStage<U>> fn)

一個CompletableFuture能夠執行完成後,將執行結果經過Function傳遞給下一個CompletionStage進行處理:

CompletableFuture<Void> future = CompletableFuture
        .supplyAsync(() -> cale(50))
        .thenCompose(i -> CompletableFuture
                .supplyAsync(() -> cale(i)))
        .thenApply(i -> Integer.toString(i))
        .thenApply(str -> "\"" + str + "\"")
        .thenAccept(System.out::println);
future.get();


另一種組和多個CompletableFuture的方法是thenCombine(),它的簽名以下:
public <U,V> CompletableFuture<V> thenCombine(
    CompletionStage<? extends U> other,
    BiFunction<? super T,? super U,? extends V> fn)

     方法thenCombine()首先完成當前CompletableFuture和other的執行,接着,將這二者的執行結果傳遞給BiFunction(該接口接受兩個參數,並有一個返回值),並返回表明BiFuntion實例的CompletableFuture對象:
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> cale(50));
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> cale(25));

CompletableFuture<Void> fu = future1.thenCombine(future2, (i, j) -> (i + j))
        .thenApply(str -> "\"" + str + "\"")
        .thenAccept(System.out::println);
fu.get();
          
相關文章
相關標籤/搜索