Java并發(fā)包 Future 續(xù)二

CompletionStage接口

CompletionStage代表異步計算過程中的某一個階段,一個階段完成以后可能會觸發(fā)另外一個階段婴谱。一個階段的計算執(zhí)行可以是一個Function,Consumer或者Runnable。一個階段的執(zhí)行可能是被單個階段的完成觸發(fā)罪治,也可能是由多個階段一起觸發(fā)

CompletableFuture

JDK5新增了Future接口娜遵,用于描述一個異步計算的結(jié)果蜕衡。雖然 Future 以及相關(guān)使用方法提供了異步執(zhí)行任務(wù)的能力,但是對于結(jié)果的獲取卻是很不方便设拟,只能通過阻塞或者輪詢的方式得到任務(wù)的結(jié)果慨仿。阻塞的方式顯然和我們的異步編程的初衷相違背,輪詢的方式又會耗費無謂的 CPU 資源纳胧,而且也不能及時地得到計算結(jié)果镰吆。

在Java8中,CompletableFuture提供了非常強大的Future的擴展功能跑慕,可以幫助我們簡化異步編程的復雜性万皿,并且提供了函數(shù)式編程的能力摧找,可以通過回調(diào)的方式處理計算結(jié)果,也提供了轉(zhuǎn)換和組合 CompletableFuture 的方法牢硅。

它實現(xiàn)了Future和CompletionStage接口
CompletableFuture實現(xiàn)了Future接口的如下策略:

  • CompletableFuture無法直接控制完成蹬耘,所以cancel操作被視為是另一種異常完成形式。方法isCompletedExceptionally可以用來確定一個CompletableFuture是否以任何異常的方式完成减余。
  • 以一個CompletionException為例综苔,方法get()和get(long,TimeUnit)拋出一個ExecutionException,對應(yīng)CompletionException位岔。為了在大多數(shù)上下文中簡化用法如筛,這個類還定義了方法join()和getNow,而不是直接在這些情況中直接拋出CompletionException抒抬。

CompletableFuture實現(xiàn)了CompletionStage接口的如下策略:

  • 為了完成當前的CompletableFuture接口或者其他完成方法的回調(diào)函數(shù)的線程杨刨,提供了非異步的完成操作。
  • 沒有顯式入?yún)xecutor的所有async方法都使用ForkJoinPool.commonPool()為了簡化監(jiān)視擦剑、調(diào)試和跟蹤妖胀,所有生成的異步任務(wù)都是標記接口AsynchronousCompletionTask的實例。
  • 所有的CompletionStage方法都是獨立于其他共有方法實現(xiàn)的抓于,因此一個方法的行為不會受到子類中其他方法的覆蓋做粤。

CompletableFuture 提供了四個靜態(tài)方法來創(chuàng)建一個異步操作。

方法
CompletableFuture<Void> runAsync(Runnable runnable)
CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)
supplyAsync(Supplier<U> supplier)
<U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor)
static void runAsync() throws ExecutionException, InterruptedException {
    CompletableFuture future = CompletableFuture.runAsync(()->{
        String value = "this is runAsync";
        System.out.println(value);
    });
    Object o = future.get();
    System.out.println(o);
}

static void supplyAsync() throws ExecutionException, InterruptedException {
    CompletableFuture<String> future = CompletableFuture.supplyAsync(()->{
        String value = "this is supplyAsync";
        System.out.println(value);
        return value;
    });
    String o = future.get();
    System.out.println(o);
}

其中supplyAsync用于有返回值的任務(wù)捉撮,runAsync則用于沒有返回值的任務(wù)怕品。Executor參數(shù)可以手動指定線程池,否則默認ForkJoinPool.commonPool()系統(tǒng)級公共線程池

計算結(jié)果完成時的回調(diào)方法
當CompletableFuture的計算結(jié)果完成巾遭,或者拋出異常的時候肉康,可以執(zhí)行特定的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)
static void whenComplete(){
    CompletableFuture.supplyAsync(()->{
        String value = "this is supplyAsync";
        System.out.println(value);
        return value;
    }).whenComplete((s, throwable) -> {
        System.out.println("this is accept");
        System.out.println(s);
        System.out.println(throwable);
    });
}


static void exceptionally() throws ExecutionException, InterruptedException {
    CompletableFuture future = CompletableFuture.supplyAsync(()->{
        String value = "this is supplyAsync";
        System.out.println(Integer.valueOf(value));
        return value;
    }).exceptionally(throwable -> {
        System.out.println(throwable);
        return "執(zhí)行報錯";
    });
    Object o = future.get();
    System.out.println(o);
}

whenComplete 和 whenCompleteAsync 的區(qū)別:

  • whenComplete:是執(zhí)行當前任務(wù)的線程執(zhí)行繼續(xù)執(zhí)行 whenComplete 的任務(wù)灼舍。

  • whenCompleteAsync:是執(zhí)行把 whenCompleteAsync 這個任務(wù)繼續(xù)提交給線程池來進行執(zhí)行吼和。

thenApply 方法
當一個線程依賴另一個線程時,可以使用 thenApply 方法來把這兩個線程串行化骑素。

方法
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)

handle 方法
handle 是執(zhí)行任務(wù)完成時對結(jié)果的處理炫乓。handle 方法和 thenApply 方法處理方式基本一樣。不同的是 handle 是在任務(wù)完成后再執(zhí)行献丑,還可以處理異常的任務(wù)末捣。thenApply 只可以執(zhí)行正常的任務(wù),任務(wù)出現(xiàn)異常則不執(zhí)行 thenApply 方法创橄。

方法
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);

thenAccept 消費處理結(jié)果
接收任務(wù)的處理結(jié)果箩做,并消費處理,無返回結(jié)果妥畏。

方法
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);

thenRun 方法
跟 thenAccept 方法不一樣的是邦邦,不關(guān)心任務(wù)的處理結(jié)果安吁。只要上面的任務(wù)執(zhí)行完成,就開始執(zhí)行 thenAccept 燃辖。

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

thenCombine 合并任務(wù)
thenCombine 會把 兩個 CompletionStage 的任務(wù)都執(zhí)行完成后鬼店,把兩個任務(wù)的結(jié)果一塊交給 thenCombine 來處理。

方法
public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);

thenAcceptBoth
當兩個CompletionStage都執(zhí)行完成后黔龟,把結(jié)果一塊交給thenAcceptBoth來進行消耗

方法
public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action)
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action, Executor executor)

applyToEither 方法
兩個CompletionStage薪韩,誰執(zhí)行返回的結(jié)果快,我就用那個CompletionStage的結(jié)果進行下一步的轉(zhuǎn)化操作捌锭。

方法
public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T, U> fn)
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn)
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T, U> fn,Executor executor)

acceptEither 方法
兩個CompletionStage,誰執(zhí)行返回的結(jié)果快罗捎,我就用那個CompletionStage的結(jié)果進行下一步的消耗操作观谦。

方法
public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor);

runAfterEither 方法
兩個CompletionStage,任何一個完成了都會執(zhí)行下一步的操作(Runnable)

方法
public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);

runAfterBoth
兩個CompletionStage桨菜,都完成了計算才會執(zhí)行下一步的操作(Runnable)

方法
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);

thenCompose
thenCompose 方法允許你對兩個 CompletionStage 進行流水線操作豁状,第一個操作完成時,將其結(jié)果作為參數(shù)傳遞給第二個操作倒得。

方法
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) ;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泻红,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子霞掺,更是在濱河造成了極大的恐慌谊路,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件菩彬,死亡現(xiàn)場離奇詭異缠劝,居然都是意外死亡,警方通過查閱死者的電腦和手機骗灶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門惨恭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人耙旦,你說我怎么就攤上這事脱羡。” “怎么了免都?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵锉罐,是天一觀的道長。 經(jīng)常有香客問我琴昆,道長氓鄙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任业舍,我火速辦了婚禮抖拦,結(jié)果婚禮上升酣,老公的妹妹穿的比我還像新娘。我一直安慰自己态罪,他們只是感情好噩茄,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著复颈,像睡著了一般绩聘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上耗啦,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天凿菩,我揣著相機與錄音,去河邊找鬼帜讲。 笑死衅谷,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的似将。 我是一名探鬼主播获黔,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼在验!你這毒婦竟也來了玷氏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤腋舌,失蹤者是張志新(化名)和其女友劉穎盏触,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體块饺,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡耻陕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了刨沦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诗宣。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖想诅,靈堂內(nèi)的尸體忽然破棺而出召庞,到底是詐尸還是另有隱情,我是刑警寧澤来破,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布篮灼,位于F島的核電站,受9級特大地震影響徘禁,放射性物質(zhì)發(fā)生泄漏诅诱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一送朱、第九天 我趴在偏房一處隱蔽的房頂上張望娘荡。 院中可真熱鬧干旁,春花似錦、人聲如沸炮沐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽大年。三九已至换薄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間翔试,已是汗流浹背轻要。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垦缅,地道東北人伦腐。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像失都,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子幸冻,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容