CompletableFuture之滅霸的故事

警告!!警告!!本文會劇透復聯四!!還未觀看過影片的同窗慎重。編程

最近復聯四上映,心疼滅霸。 「歸隱山林老農,竟招衆人砍頭」。

今天來講說CompletableFuture之滅霸的故事。bash

CompletableFuture,它是Java1.8提供的用來支持異步編程的工具類。在Java1.5裏就提供了Future接口app

咱們知道Future是強大的可是在多任務有聚合關係的狀況下用起來就有點麻煩,而CompletableFuture 就是用來解決任務之間的聚合關係的。對於滅霸來講他的得彙集六顆無限寶石,加上一個彙集寶石力量的手套,才能打響指!因此最終打響指這個任務依賴於彙集六顆寶石的任務和有手套。異步

CompletableFuture之滅霸的故事

話很少說先上代碼,復聯四的故事是這樣的(因演示CompletableFuture須要,沒有嚴格按照劇情)異步編程

CompletableFuture<String> infinityStones = CompletableFuture.supplyAsync(() -> "六顆無限寶石");
        CompletableFuture<Void> mittens = CompletableFuture.runAsync(() -> {
            System.out.println("用於集合六顆無限寶石力量來打響指的手套");
        });
        CompletableFuture<String> thanosSnap = mittens.thenCombine(infinityStones, (m, stons) -> {
            System.out.println("獲取" + stons);
            System.out.println("把寶石放到手套上");
            System.out.println("滅霸:我就是天命!(打響指)");
            int a = 1 / 0;       //鋼鐵俠自告奮勇,替換了手套;
            return "呵呵寂寞,一羣渣渣";
        }).exceptionally(e ->{
            System.out.println("鋼鐵俠搶奪了手套,舉起手臂,輕輕打響指");
            return "鋼鐵俠:i am iron man";
        });
        System.out.println(thanosSnap.join());
        System.out.println("滅霸看着滿天成灰的手下..心中流下了痛苦的淚水");
    }
     
     ##輸出的故事情節以下
     用於集合六顆無限寶石力量來打響指的手套
     獲取六顆無限寶石
     把寶石放到手套上
     滅霸:我就是天命!(打響指)
     鋼鐵俠搶奪了手套,舉起手臂,輕輕打響指
     鋼鐵俠:i am iron man
     滅霸看着滿天成灰的手下..心中流下了痛苦的淚水
複製代碼

可憐的滅霸就這樣離開了咱們,還有咱們的鋼鐵俠帥的一批。I love you three thousand times.工具

CompletableFuture

我們仍是先回到CompletableFuture上,解釋一下上面的方法。CompletableFuture主要是經過下面四個靜態方法來建立的。post

public static CompletableFuture<Void> runAsync(Runnable runnable) //使用默認線程池(ForkJoinPool)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) //使用傳入的線程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) //使用默認線程池(ForkJoinPool)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) //使用傳入的線程池
複製代碼

runAsyncsupplyAsync的差異在於runAsync方法不支持返回值而supplyAsync支持。ui

CompletionStage

這裏還須要知道一個東西CompletionStage,它能夠認爲你的異步計算中的一個階段,經過它能夠很清晰的描述你的任務流的各任務之間的時序關係。如串行關係,and關係,or關係。CompletableFuture實現了CompletionStagespa

CompletionStage 接口中的串行方法

如下爲CompletionStage接口中串行的方法,都是任務之間有依賴關係,必須一個任務執行完另外一個任務才能執行。有Async的話就是不在當前線程內執行。異步再起一個線程執行。線程

thenApply 能接收參數也支持返回值,也就是接收上一階段的輸出做爲本階段的輸入

thenAccept 支持接收參數可是沒有返回值。

thenRun 不接受參數也不支持返回值,名副其實,就是run。

thenCompose 容許對兩個 CompletionStage 進行流水線操做。

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)

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

public CompletionStage<Void> thenRun(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);

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) ;
複製代碼

CompletionStage 接口中and關係的方法

如下爲CompletionStage接口中and關係的方法,強調的不是順序而是兩個任務都完成了就行,沒前後的要求。咱們上面代碼用到的就是and關係。參數類型刪掉了,就留個方法名有點印象就好了,具體仍是得本身用的時候看。幾個方法的差異就是參數的不一樣。

public <U,V> CompletionStage<V> thenCombine(other,fn);
public <U,V> CompletionStage<V> thenCombineAsync(other,fn);
public <U,V> CompletionStage<V> thenCombineAsync(other,fn,executor);

public <U> CompletionStage<Void> thenAcceptBoth(other,action);
public <U> CompletionStage<Void> thenAcceptBothAsync(other,action);
public <U> CompletionStage<Void> thenAcceptBothAsync(other,action, executor);

public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);
複製代碼

CompletionStage 接口中or關係的方法

or的關係就是兩個任務,裏面只要有一個完成就執行下一階段的。若是是有返回值的話,那就是誰先返回用誰的結果執行下一個階段的任務。

public <U> CompletionStage<U> applyToEither(other fn);
public <U> CompletionStage<U> applyToEitherAsync(other,fn);
public <U> CompletionStage<U> applyToEitherAsync(other, fn,executor);

public CompletionStage<Void> acceptEither(other,action);
public CompletionStage<Void> acceptEitherAsync(other,action);
public CompletionStage<Void> acceptEitherAsync(other,action,executor);

public CompletionStage<Void> runAfterEither(other,action);
public CompletionStage<Void> runAfterEitherAsync(other,action);
public CompletionStage<Void> runAfterEitherAsync(other,action,executor);
複製代碼

CompletionStage 異常處理

在上述的參數方法內是不能拋出可檢查異常,可是運行有時候仍是會異常。CompletionStage 就提供瞭如下幾種處理異常的方法。 whenComplete和handle就相似try catch中的finally(我姓方平行四邊形的方),反正會執行到這個方法,就能夠用它來處理異常,兩個的差異就是whenComplete不支持返回結果,handle支持。

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 <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,Executor executor);

public CompletableFuture<T> exceptionally(Function<Throwable,? extends T> fn)
複製代碼

總結

若是是任務之間有聚合關係就能夠用CompletableFuture來解決!Java幫你寫好的工具類不用白不用!


若有錯誤歡迎指正! 我的公衆號:yes的練級攻略

相關文章
相關標籤/搜索