Java8并發(fā)新特性CompletableFuture
1.CompletableFuture是什么?
各位小伙伴是否有一種感覺,整天大量時(shí)間沉迷于業(yè)務(wù)開發(fā)的同時(shí),缺少對(duì)于一些技術(shù)更新的關(guān)注,忽略掉了很多實(shí)用又簡(jiǎn)單的方法,以往我們做異步任務(wù)的時(shí)候都習(xí)慣于使用Callable或者Runnable接口去實(shí)現(xiàn),今天我們就來聊聊與之不同的CompletableFuture類。
CompletableFuture針對(duì)Future接口做了改進(jìn),相比Callable/Runnable接口它支持多任務(wù)進(jìn)行鏈?zhǔn)秸{(diào)用、組合、多任務(wù)并發(fā)處理。很多時(shí)候我們?cè)谠O(shè)計(jì)過程中會(huì)想在一個(gè)異步任務(wù)執(zhí)行完成后,直接獲取它的結(jié)果傳遞給下一個(gè)任務(wù)繼續(xù)執(zhí)行后續(xù)的流程,這時(shí)候CompletableFuture的作用就來了。
CompletableFuture類關(guān)系圖:
從以下類圖可以看到,CompletableFuture實(shí)現(xiàn)了Future和CompletionStage兩個(gè)接口,F(xiàn)uture提供了獲取任務(wù)執(zhí)行結(jié)果和任務(wù)執(zhí)行狀態(tài)的功能。 CompletionStage表示一個(gè)任務(wù)的執(zhí)行階段,提供了諸多方法支持了多任務(wù)的聚合功能。
2.CompletableFuture的方法使用說明
2.1 CompletableFuture類提供幾個(gè)靜態(tài)方法來進(jìn)行異步操作
supplyAsync與runAsync主要用于構(gòu)建異步事件。
supplyAsync:帶有返回值的異步任務(wù),支持在默認(rèn)線程池ForkJoinPool.commonPool()中完成異步任務(wù),也可以使用自定義線程池執(zhí)行異步任務(wù),結(jié)果返回一個(gè)新的CompletableFuture,返回結(jié)果類型U。最終的任務(wù)執(zhí)行結(jié)果可通過返回CompletableFuture對(duì)象的 get()/join() 方法獲取返回值。
// 使用默認(rèn)線程池 public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {...} // 使用自定義線程池Executor public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) {...} // ====================================demo華麗分割線============================================ CompletableFuture<String> supplyAsyncFuture = CompletableFuture.supplyAsync(() -> { log.info("executing supplyAsync task ..."); return "this is supplyAsync"; }); // 進(jìn)入阻塞獲取異步任務(wù)結(jié)果 log.info(supplyAsyncFuture.get()); // 輸出結(jié)果:this is supplyAsync
runAsync:不帶返回值的異步任務(wù),支持在默認(rèn)線程池ForkJoinPool.commonPool()中完成異步任務(wù),也可以使用自定義線程池執(zhí)行異步任務(wù),結(jié)果返回一個(gè)新的CompletableFuture,返回結(jié)果類型為Void,也就是無返回值。
public static CompletableFuture<Void> runAsync(Runnable runnable) {...} public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) {...} // ====================================demo華麗分割線============================================ CompletableFuture<Void> runAsyncFuture = CompletableFuture.runAsync(() -> { log.info("executing runAsync task ..."); }); runAsyncFuture.get();
allOf:多個(gè)CompletableFuture任務(wù)并發(fā)執(zhí)行,所有CompletableFuture任務(wù)完成時(shí),返回一個(gè)新的CompletableFuture對(duì)象,其返回值為Void,也就是無返回值。
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {...} // ====================================demo華麗分割線============================================ // allOf,可傳遞返回值不同類型的future,最終結(jié)果按自己設(shè)計(jì)預(yù)期處理即可 CompletableFuture<String> cf11 = CompletableFuture.supplyAsync(() -> { log.info("executing supplyAsync task cf11 ..."); return "this is supplyAsync"; }); CompletableFuture<String> cf12 = CompletableFuture.supplyAsync(() -> { log.info("executing supplyAsync task cf12 ..."); return "this is supplyAsync"; }); CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(cf11, cf12); allOfFuture.get();
anyOf:多個(gè)CompletableFuture任務(wù)并發(fā)執(zhí)行,只要有一個(gè)CompletableFuture任務(wù)完成時(shí),就會(huì)返回一個(gè)新的CompletableFuture對(duì)象,并返回該CompletableFuture執(zhí)行完成任務(wù)的返回值。
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {...} // ====================================demo華麗分割線============================================ CompletableFuture<String> cf21 = CompletableFuture.supplyAsync(() -> { log.info("executing supplyAsync task cf21 ..."); return "this is supplyAsync cf21"; }); CompletableFuture<String> cf22 = CompletableFuture.supplyAsync(() -> { log.info("executing supplyAsync task cf22 ..."); return "this is supplyAsync cf22"; }); CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(cf21, cf22); log.info("{}", anyOfFuture.get()); // 輸出結(jié)果:this is supplyAsync cf21或cf22
2.2 獲取異步任務(wù)執(zhí)行結(jié)果的方法 get()/join()
join()和get()方法都是CompletableFuture對(duì)象基于阻塞的方式來獲取異步任務(wù)執(zhí)行結(jié)果。
- get方法會(huì)拋出顯示異常必須捕獲處理,任務(wù)允許被中斷拋出InterruptedException異常,通過帶有超時(shí)時(shí)間的阻塞方式獲取異步任務(wù)執(zhí)行結(jié)果,超時(shí)等待無結(jié)果則中斷任務(wù)拋出TimeoutException異常。
- join方法會(huì)拋出未檢查異常,與get()方法不同的是join()方法不允許被中斷。
// 可中斷,可設(shè)置超時(shí)時(shí)間 public T get() throws InterruptedException, ExecutionException {...} public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {...} /** * 不可中斷 */ public T join() {...}
3.CompletionStage的方法使用說明
CompletionStage表示一個(gè)任務(wù)的執(zhí)行階段,每個(gè)任務(wù)都會(huì)返回一個(gè)CompletionStage對(duì)象,可以對(duì)多個(gè)CompletionStage對(duì)象進(jìn)行串行、并行或者聚合的方式來進(jìn)行下階段的操作,也就是說實(shí)現(xiàn)異步任務(wù)的回調(diào)功能。CompletionStage總共提供了38個(gè)方法來實(shí)現(xiàn)多個(gè)CompletionStage任務(wù)的各種操作, 接下來我們就針對(duì)這些方法分類來了解一下。
以下類型均有三種使用方式:
- thenAccept:方法名不帶Async的使用主線程同步執(zhí)行回調(diào)函數(shù),不做異步處理
- thenAcceptAsync:方法名帶Async,但是無executor參數(shù)的,使用默認(rèn)線程池ForkJoinPool.commonPool異步執(zhí)行任務(wù)
- thenAcceptAsync:方法名帶Async,有executor參數(shù)的,使用自定義線程池異步執(zhí)行任務(wù)
3.1 純消費(fèi)類型
- 依賴單個(gè)任務(wù)完成(thenAccept):由上一個(gè)CompletionStage任務(wù)執(zhí)行完成的結(jié)果傳遞到action進(jìn)行回調(diào)處理,即僅僅消費(fèi)了上一個(gè)CompletionStage任務(wù)的返回值,回調(diào)處理結(jié)果無返回值。
// 不使用線程池,僅依賴當(dāng)前線程執(zhí)行,不做異步 public CompletionStage<Void> thenAccept(Consumer<? super T> action); // 使用默認(rèn)線程池ForkJoinPool.commonPool執(zhí)行任務(wù) public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action); // 使用自定義線程池執(zhí)行任務(wù) public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor); // ====================================demo華麗分割線============================================ CompletableFuture.supplyAsync(() -> "this is supplyAsync") .thenAcceptAsync((result) -> { log.info("{} thenAcceptAsync", result); }).join(); // 輸出結(jié)果:this is supplyAsync thenAcceptAsync
依賴兩個(gè)任務(wù)都完成(thenAcceptBoth):兩個(gè)CompletionStage任務(wù)并發(fā)執(zhí)行,必須都完成了才執(zhí)行action回調(diào)處理,即僅僅消費(fèi)了兩個(gè)CompletionStage任務(wù)的返回值,回調(diào)處理結(jié)果無返回值。
/** * 額外多了CompletionStage參數(shù)表示CompletionStage任務(wù)依賴的另一個(gè)CompletionStage任務(wù) * action接收兩個(gè)參數(shù),分別表示兩個(gè)CompletionStage任務(wù)的返回值 */ public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action); // 原理同上,使用默認(rèn)線程池執(zhí)行異步任務(wù) public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action); // 原理同上,使用自定義線程池執(zhí)行異步任務(wù) public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other, BiConsumer<? super T, ? super U> action, Executor executor); // ====================================demo華麗分割線============================================ CompletableFuture<String> cf311 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf311"); CompletableFuture<String> cf312 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf312"); cf311.thenAcceptBothAsync(cf312, (r1, r2) -> { log.info("{} and {}", r1, r2); }).join(); // 輸出結(jié)果:this is supplyAsync cf311 and this is supplyAsync cf312
依賴兩個(gè)任務(wù)中的任何一個(gè)完成(acceptEither):兩個(gè)CompletionStage任務(wù)并發(fā)執(zhí)行,只要其中一個(gè)先完成了就攜帶返回值執(zhí)行action回調(diào)處理,即僅僅消費(fèi)了優(yōu)先完成的CompletionStage任務(wù)的返回值,回調(diào)處理結(jié)果無返回值。
/** * 類似thenAcceptBothAsync,只不過acceptEither只需兩個(gè)任務(wù)中的其中一個(gè)完成即可回調(diào)action * action中的值為兩個(gè)任務(wù)中先執(zhí)行完任務(wù)的返回值 */ 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); // ====================================demo華麗分割線============================================ CompletableFuture<String> cf311 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf311"); CompletableFuture<String> cf312 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf312"); cf311.acceptEitherAsync(cf312, (r) -> { log.info(r); // 輸出結(jié)果:this is supplyAsync cf311或cf312 }).join();
3.2 有返回值類型
依賴單個(gè)任務(wù)完成(thenApply):由上一個(gè)CompletionStage任務(wù)執(zhí)行完成的結(jié)果傳遞到action進(jìn)行回調(diào)處理,即不止消費(fèi)了上一個(gè)CompletaionStage任務(wù)的返回值,同時(shí)回調(diào)處理結(jié)果也有返回值
public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn); public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn); public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor); // ====================================demo華麗分割線============================================ CompletableFuture<String> cf32 = CompletableFuture.supplyAsync(() -> "this is supplyAsync") .thenApplyAsync(result -> result + " and thenApplyAsync"); log.info(cf32.join()); // 輸出結(jié)果:this is supplyAsync and thenApplyAsync
依賴兩個(gè)任務(wù)都完成(thenCombine):兩個(gè)CompletionStage任務(wù)并發(fā)執(zhí)行,必須都完成了才執(zhí)行action回調(diào)處理,即不止消費(fèi)了兩個(gè)CompletaionStage任務(wù)的返回值,同時(shí)回調(diào)處理結(jié)果也有返回值。
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); // ====================================demo華麗分割線============================================ CompletableFuture<String> cf321 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf321"); CompletableFuture<String> cf322 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf322"); CompletableFuture<String> thenCombineFuture = cf321.thenCombineAsync(cf322, (r1, r2) -> { return r1 + " and " + r2; }); log.info(thenCombineFuture.join()); // 輸出結(jié)果:this is supplyAsync cf321 and this is supplyAsync cf322
依賴兩個(gè)任務(wù)中的任何一個(gè)完成(applyToEither):兩個(gè)CompletionStage任務(wù)并發(fā)執(zhí)行,只要其中一個(gè)任務(wù)執(zhí)行完成就會(huì)action回調(diào)處理,即不止消費(fèi)了優(yōu)先完成的CompletionStage的返回值,同時(shí)回調(diào)處理結(jié)果也有返回值。
// 原理同3.1的acceptEither,只不過applyToEither任務(wù)執(zhí)行完成會(huì)返回一個(gè)帶有返回值的CompletionStage 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); // ====================================demo華麗分割線============================================ CompletableFuture<String> cf321 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf321"); CompletableFuture<String> cf322 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf322"); CompletableFuture<String> thenCombineFuture = cf321.applyToEitherAsync(cf322, (r) -> { return r; }); log.info(thenCombineFuture.join()); // 輸出結(jié)果:this is supplyAsync cf321或cf322
3.3 不消費(fèi)也不返回類型
依賴單個(gè)任務(wù)完成(thenRun):?jiǎn)蝹€(gè)CompletionStage任務(wù)執(zhí)行完成回調(diào)action處理,即執(zhí)行action回調(diào)方法無參數(shù),回調(diào)處理結(jié)果也無返回值。
// 上一個(gè)CompletionStage任務(wù)執(zhí)行完成后直接回調(diào)action處理,無返回值 public CompletionStage<Void> thenRun(Runnable action); // 同上,使用默認(rèn)線程池執(zhí)行action處理 public CompletionStage<Void> thenRunAsync(Runnable action); // 同上,使用自定義線程池執(zhí)行action處理 public CompletionStage<Void> thenRunAsync(Runnable action, Executor executor); // ====================================demo華麗分割線============================================ CompletableFuture.runAsync(() -> { // TODO }).thenRunAsync(() -> { log.info("this is thenRunAsync"); // 輸出結(jié)果:this is thenRunAsync }).join();
依賴兩個(gè)任務(wù)都完成(runAfterBoth):兩個(gè)CompletionStage任務(wù)并發(fā)執(zhí)行,必須兩個(gè)任務(wù)都完成才執(zhí)行action回調(diào)處理,即執(zhí)行action回調(diào)方法無參數(shù),回調(diào)處理結(jié)果也無返回值。
// 原理同3.1的thenAcceptBoth,只不過runAfterBoth的action回調(diào)處理不接收參數(shù)且任務(wù)執(zhí)行完成無返回值 public CompletionStage<Void> runAfterBoth(CompletionStage<?> other, Runnable action); // 同上,使用默認(rèn)線程池執(zhí)行action處理 public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action); // 同上,使用自定義線程池執(zhí)行action處理 public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action, Executor executor); // ====================================demo華麗分割線============================================ CompletableFuture<String> cf331 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf331"); CompletableFuture<String> cf332 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf332"); cf331.runAfterBoth(cf332, () -> { log.info("this is runAfterBoth"); }).join(); // 輸出結(jié)果:this is runAfterBoth
依賴兩個(gè)任務(wù)中的任何一個(gè)完成(runAfterEither):兩個(gè)CompletionStage任務(wù)并發(fā)執(zhí)行,只需其中任何一個(gè)任務(wù)完成即可回調(diào)action處理,即執(zhí)行action回調(diào)方法無參數(shù),回調(diào)處理結(jié)果也無返回值。
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); // ====================================demo華麗分割線============================================ CompletableFuture<String> cf331 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf331"); CompletableFuture<String> cf332 = CompletableFuture.supplyAsync(() -> "this is supplyAsync cf332"); cf331.runAfterEitherAsync(cf332, () -> { log.info("this is runAfterEitherAsync"); }).join(); // 輸出結(jié)果:this is runAfterEitherAsync
3.4 組合類型
thenCompose:存在先后關(guān)系的兩個(gè)任務(wù)進(jìn)行串行組合,由第一個(gè)CompletionStage任務(wù)執(zhí)行結(jié)果作為參數(shù)傳遞給第二個(gè)CompletionStage任務(wù),最終返回第二個(gè)CompletionStage。
public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn); public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn); public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor); // ====================================demo華麗分割線============================================ CompletableFuture<String> supplyFuture = CompletableFuture.supplyAsync(() -> { return "this is supplyAsync"; }); CompletableFuture<String> thenComposeFuture = supplyFuture.thenComposeAsync((r) -> { return CompletableFuture.supplyAsync(() -> { return r + " and this is thenComposeAsync"; }); }); log.info(thenComposeFuture.join()); // 輸出結(jié)果:this is supplyAsync and this is thenComposeAsync
3.5 任務(wù)事件類型
CompletionStage接口也支持類似我們常用的try-catch-finally中的finally的作用,無論這個(gè)任務(wù)的執(zhí)行結(jié)果是正常還是出現(xiàn)異常的情況,都必須要去執(zhí)行的一個(gè)代碼塊。在CompletionStage接口提供了以下兩種接口回調(diào)的形式(whenComplete、handle),并支持主線程同步執(zhí)行同時(shí)也支持使用默認(rèn)線程池,或者使用自定義線程池去異步執(zhí)行最終的回調(diào)處理。例如我們一個(gè)事務(wù)操作,無論這段代碼執(zhí)行是否成功,我們都必須要去關(guān)閉事務(wù)。
任務(wù)完成事件(whenComplete):結(jié)果無返回值,若出現(xiàn)異常執(zhí)行完whenComplete回調(diào)處理完成后將中斷主線程的運(yùn)行。
// 1.whenComplete回調(diào)函數(shù)中Throwable對(duì)象不對(duì)空代表出現(xiàn)異常,為空則表示無異常 public CompletionStage<T> whenComplete(BiConsumer<? super T, ? super Throwable> action); public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action); public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action, Executor executor); // ====================================demo華麗分割線============================================ CompletableFuture<String> whenCompleteFufute = CompletableFuture.supplyAsync(() -> { int a = 0; int b = 100 / a; return "this is supplyAsync normal"; }).whenCompleteAsync((r, th) -> { if (th != null) { log.error("this is whenCompleteAsync error"); } else { log.info("this is whenCompleteAsync success"); } }); log.info(whenCompleteFufute.join()); // 輸出結(jié)果:this is whenCompleteAsync error
任務(wù)完成回調(diào)事件(handle):結(jié)果有返回值,若出現(xiàn)異常執(zhí)行完handle回調(diào)處理完成后將繼續(xù)執(zhí)行主線程的后續(xù)操作,不中斷主線程運(yùn)行。
// 2.handle回調(diào)函數(shù)中Throwable對(duì)象不對(duì)空代表出現(xiàn)異常,為空則表示無異常 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); // ====================================demo華麗分割線============================================ CompletableFuture<String> whenCompleteFufute = CompletableFuture.supplyAsync(() -> { int a = 0; int b = 100 / a; return "this is supplyAsync normal"; }).handleAsync((r, th) -> { if (th != null) { return "this is handleAsync error"; } else { return "this is handleAsync success"; } }); log.info(whenCompleteFufute.join()); // 輸出結(jié)果:this is handleAsync error log.info("main thread is running"); // 輸出結(jié)果:main thread is running
4.CompletionStage異常處理方法
exceptionally:只要是個(gè)程序,就會(huì)有異常出現(xiàn)的情況,例如一個(gè)CompletionStage任務(wù),如果執(zhí)行過程中出現(xiàn)異常,我們?yōu)榱吮WC異常情況下程序能夠正常處理業(yè)務(wù)邏輯,那么在這里我們就可以使用exceptionally進(jìn)行異?;卣{(diào)處理。當(dāng)CompletionStage任務(wù)出現(xiàn)異常時(shí)就會(huì)觸發(fā)回調(diào)exceptionally,否則CompletionStage任務(wù)正常執(zhí)行業(yè)務(wù)不進(jìn)行異?;卣{(diào)處理。
public CompletionStage<T> exceptionally(Function<Throwable, ? extends T> fn); // ====================================demo華麗分割線============================================ CompletableFuture<String> exceptionallyFuture = CompletableFuture.supplyAsync(() -> { int a = 0; int b = 10 / a; // 除數(shù)為0將拋異常 return "this is supplyAsync normal"; }).exceptionally(th -> { log.error("exception:{}", th.getMessage()); return "this is exceptionally"; }); log.info(exceptionallyFuture.join()); // 輸出結(jié)果:this is exceptionally
注:以下這兩種情況可能大家在實(shí)際開發(fā)過程中會(huì)比較少見,但還是得在這里做個(gè)提醒,以免到最后準(zhǔn)備不充分出現(xiàn)設(shè)計(jì)上的缺陷。
- 當(dāng)whenCompleteAsync與exceptionally同時(shí)使用時(shí),若出現(xiàn)異常情況,由于exceptionally有返回值,所以優(yōu)先執(zhí)行whenCompleteAsync,后執(zhí)行exceptionally。
- 當(dāng)handleAsync與exceptionally同時(shí)出現(xiàn)時(shí),由于handleAsync已經(jīng)包含了exceptionally的所有操作,即handleAsync回調(diào)有返回值,且有Throwable異常對(duì)象能夠進(jìn)行異常處理,所以這兩者同時(shí)出現(xiàn)時(shí)exceptionally將失效。
5.方法類型總結(jié)
根據(jù)以上的方法我們可以總結(jié)出這些任務(wù)其實(shí)就分為三大類,相當(dāng)于通過CompletionStage的回調(diào)機(jī)制來實(shí)現(xiàn)多個(gè)任務(wù)串、多個(gè)任務(wù)并行、多個(gè)任務(wù)聚合的操作,因此CompletableFuture對(duì)于異步任務(wù)的處理提供了更加強(qiáng)大的編程模型。所以說java8提供的CompletableFuture類相對(duì)原來的Future接口來說提供了一些鏈?zhǔn)降木幊?,省去了我們很多異步任?wù)回調(diào)操作復(fù)雜的步驟,讓我們這些碼農(nóng)們能夠有更高的效率輸出產(chǎn)品。
到此這篇關(guān)于Java8并發(fā)新特性CompletableFuture的文章就介紹到這了,更多相關(guān)Java8 CompletableFuture內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
從零開始學(xué)SpringBoot如何開始使用圖文詳解
這篇文章主要介紹了從零開始學(xué)SpringBoot如何開始使用,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09AntDesign多環(huán)境配置啟動(dòng)過程詳解
這篇文章主要為大家介紹了AntDesign多環(huán)境配置啟動(dòng)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11spring自定義注解實(shí)現(xiàn)攔截器的實(shí)現(xiàn)方法
本篇文章主要介紹了spring自定義注解實(shí)現(xiàn)攔截器的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08Java進(jìn)階教程之運(yùn)行時(shí)類型識(shí)別RTTI機(jī)制
這篇文章主要介紹了Java進(jìn)階教程之運(yùn)行時(shí)類型識(shí)別RTTI機(jī)制,在Java運(yùn)行時(shí),RTTI維護(hù)類的相關(guān)信息,比如多態(tài)(polymorphism)就是基于RTTI實(shí)現(xiàn)的,需要的朋友可以參考下2014-09-09Java中InputSteam怎么轉(zhuǎn)String
面了一位實(shí)習(xí)生,叫他給我說一下怎么把InputStream轉(zhuǎn)換為String,這種常規(guī)的操作,他竟然都沒有用過我準(zhǔn)備結(jié)合工作經(jīng)驗(yàn),整理匯集出了InputStream 到String 轉(zhuǎn)換的十八般武藝,助大家闖蕩 Java 江湖一臂之力,需要的朋友可以參考下2021-06-06Java傳入用戶名和密碼并自動(dòng)提交表單實(shí)現(xiàn)登錄到其他系統(tǒng)的實(shí)例代碼
這篇文章主要介紹了Java傳入用戶名和密碼并自動(dòng)提交表單實(shí)現(xiàn)登錄到其他系統(tǒng),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01