Java8?CompletableFuture?runAsync學習總結submit()?execute()等
一般的 Executors 的 execute以及submit
并發(fā)包下 Executors 創(chuàng)建的線程存在 一個 execute(),以及三個 submit()
不同的是使用 execute() 執(zhí)行的任務是沒有返回值的,使用 submit() 則是存在返回值的,這與接下里要說的 CompletableFuture.runAsync 有些類似。


測試代碼如下:
@Test
public void justFor(){
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Float> submit = executorService.submit(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
Float aFloat = null;
try {
aFloat = submit.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// 根據自己需要決定是否需要調用關閉線程
// executorService.shutdown();
System.out.println("aFloat = " + aFloat);
}
結果:
Thread.currentThread() = Thread[pool-2-thread-1,5,main]
aFloat = 1.03
使用 submit 可以通過 get獲取線程中任務的返回結果,可以通過對象獲取當前狀態(tài) isDone 或者 isCancelled ;
子線程異步執(zhí)行,主線程休眠等待子線程執(zhí)行完成,子線程執(zhí)行完成后喚醒主線程,主線程獲取任務執(zhí)行結果后退出
此時我加入一個異常代碼,使其必定出錯再來看看結果
@Test
public void justFor(){
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Float> submit = executorService.submit(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
int ii = 1/0;
return 1.2f;
});
Float aFloat = null;
try {
aFloat = submit.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
// executorService.shutdown();
System.out.println("aFloat = " + aFloat);
}
執(zhí)行結果:

此時即使異常依舊終止了子線程以及主線程的執(zhí)行。
CompletableFuture 的 supplyAsync() / runAsync()
supplyAsync表示創(chuàng)建帶返回值的異步任務,相當于ExecutorService submit(Callable< T> task)runAsync表示創(chuàng)建無返回值的異步任務,相當于ExecutorService submit(Runnable task)方法,這兩個方法效果與 submit 一致
示例代碼:
@Test
public void justFor(){
CompletableFuture<Float> floatCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
try {
Float aFloat = floatCompletableFuture.get();
System.out.println("Thread.currentThread() = " + Thread.currentThread());
System.out.println("aFloat = " + aFloat);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}輸出結果:
Thread.currentThread() = Thread[ForkJoinPool.commonPool-worker-1,5,main]
Thread.currentThread() = Thread[main,5,main]
aFloat = 1.03
日志中 ForkJoinPool 為jdk1.7 提供的一個新的分而治之的性能更好的并發(fā)處理線程池,比一般的Executors 更好一點,適用于高密度計算的任務。
但也可以如此寫

即將該任務提交到指定的線程池中執(zhí)行該任務;
輸出的線程池不一致
類似的 runAsync() 也可以這樣,使用自己的異步線程或者提交到指定的線程池中執(zhí)行

可以看得出使用第二個參數均提供了可以指定 Executor 沒有指定時默認使用 ForkJoinPool.commonPool()
一般的
runAsync 如下:
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return;
});可以看得出 并沒有任何返回值
CompletableFuture 的 thenApply() / thenApplyAsync()

thenApply 表示某個任務執(zhí)行完成后執(zhí)行的動作即回調方法,會將該任務的執(zhí)行結果即方法的返回值會作為作為入參傳遞到接下來的回調方法中
示例代碼:
@Test
public void justFor(){
CompletableFuture<Float> floatCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
CompletableFuture<Float> floatCompletableFuture1 = floatCompletableFuture.thenApply((resultFloat) -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
System.out.println("接受上一個 resultFloat = " + resultFloat);
return 2.01f;
});
CompletableFuture<Float> floatCompletableFuture2 = floatCompletableFuture1.thenApplyAsync((result2) -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
System.out.println("result2 = " + result2);
return 2.21f;
});
try {
Float aFloat = floatCompletableFuture.get();
System.out.println("Thread.currentThread() = " + Thread.currentThread());
System.out.println("aFloat = " + aFloat);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}輸出結果:
Thread.currentThread() = Thread[ForkJoinPool.commonPool-worker-1,5,main]
Thread.currentThread() = Thread[main,5,main]
接受上一個 resultFloat = 1.03
Thread.currentThread() = Thread[main,5,main]
Thread.currentThread() = Thread[ForkJoinPool.commonPool-worker-1,5,main]
aFloat = 1.03
result2 = 2.01
thenApplyAsync 與 thenApply 區(qū)別:
thenApplyAsync將任務異步處理,可以選擇提交到某一個線程池中執(zhí)行thenApply則將會在上一個任務的同一個線程中執(zhí)行
上面代碼也可以連著書寫如下:

CompletableFuture 的 thenAccept() / thenRun()
thenAccept同thenApply接收上一個任務的返回值作為參數但是沒有返回值thenAcceptAsync同上但為異步線程,可以指定提交到某一個線程池中thenRun方法沒有入參,也沒有返回值thenRunAsync同上但為異步線程,可以指定提交到某一個線程池中
示例代碼:
@Test
public void justFor(){
CompletableFuture<Float> floatCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
CompletableFuture<Void> floatCompletableFuture1= floatCompletableFuture.thenApply((resultFloat) -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
System.out.println("接受上一個 resultFloat = " + resultFloat);
return 2.01f;
}).thenAccept((result)->{
System.out.println("Thread.currentThread() = " + Thread.currentThread());
System.out.println("result = " + result);
}).thenRun(()->{
System.out.println("Thread.currentThread() = " + Thread.currentThread());
System.out.println(" doNothing");
});
}CompletableFuture exceptionally
指定某個任務執(zhí)行異常時執(zhí)行的回調方法,會將拋出異常作為參數傳遞到回調方法中,如果該任務正常執(zhí)行則 exceptionally方法返回的CompletionStage的result就是該任務正常執(zhí)行的結果
正常示例:
@Test
public void justFor(){
CompletableFuture<Float> floatCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
// float ii = 1/0;
return 1.03f;
});
CompletableFuture<Float> exceptionally = floatCompletableFuture.exceptionally((exception) -> {
System.out.println("catch exception");
exception.printStackTrace();
return 0.0f;
});
floatCompletableFuture.thenAccept((result)->{
System.out.println("is OK");
System.out.println("result = " + result);
});
}輸出結果:
Thread.currentThread() = Thread[ForkJoinPool.commonPool-worker-1,5,main]
is OK
異常示例:
@Test
public void justFor(){
CompletableFuture<Float> floatCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
int a = 121/0;
return 1.03f;
});
CompletableFuture<Float> exceptionally = floatCompletableFuture.exceptionally((exception) -> {
System.out.println("catch exception");
exception.printStackTrace();
return 0.0f;
});
floatCompletableFuture.thenAccept((result)->{
System.out.println("is OK");
System.out.println("result = " + result);
});
}結果:
Thread.currentThread() = Thread[ForkJoinPool.commonPool-worker-1,5,main]
catch exception
CompletableFuture whenComplete
當某個任務執(zhí)行完成后執(zhí)行的回調方法,會將執(zhí)行結果或者執(zhí)行期間拋出的異常傳遞給回調方法
- 正常執(zhí)行則異常為null,回調方法對應的CompletableFuture的result和該任務一致
- 異常執(zhí)行,則get方法拋出異常
- 同樣提供 Async 異步相關方法
正常:
@Test
public void justFor(){
CompletableFuture<Float> floatCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
floatCompletableFuture.whenComplete((result, exception) -> {
System.out.println("result = " + result);
System.out.println("exception = " + exception);
});
}
輸出:
Thread.currentThread() = Thread[ForkJoinPool.commonPool-worker-1,5,main]
result = 1.03
exception = null
異常時示例:
public static void main(String[] args) {
CompletableFuture<Float> floatCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
int ii = 12 / 0;
return 1.03f;
});
floatCompletableFuture.whenComplete((result, exception) -> {
System.out.println("result = " + result);
System.out.println("exception = " + exception);
});
}
輸出:
Thread.currentThread() = Thread[ForkJoinPool.commonPool-worker-1,5,main]
result = null
exception = java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
CompletableFuture handle
與 whenComplete 基本一致
區(qū)別在于handle的回調方法有返回值,且handle方法返回的CompletableFuture的result是回調方法的執(zhí)行結果或者回調方法執(zhí)行期間拋出的異常,與原始CompletableFuture的result無關
示例代碼:
@Test
public void justFor(){
CompletableFuture<Float> floatCompletableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
int ii = 12 / 0;
return 1.03f;
});
floatCompletableFuture.handle((result, exception) -> {
System.out.println("result = " + result);
System.out.println("exception = " + exception);
return "???";
});
}CompletableFuture 組合處理 thenCombine / thenAcceptBoth / runAfterBoth
三個方法都是將兩個 CompletableFuture 組合起來
只有這兩個都正常執(zhí)行完了才會執(zhí)行某個任務區(qū)別在于
thenCombine會將兩個任務的執(zhí)行結果作為方法入參傳遞到指定方法中,且該方法有返回值;thenAcceptBoth 同樣將兩個任務的執(zhí)行結果作為方法入參,但是無返回值;runAfterBoth沒有入參,也沒有返回值。注意兩個任務中只要有一個執(zhí)行異常,則將該異常信息作為指定任務的執(zhí)行結果
同時這些也提供了Async 異步方法
示例代碼:
@Test
public void justFor(){
CompletableFuture<Float> a1 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
CompletableFuture<Float> a2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 2.03f;
});
// 傳遞結果 有返回值
CompletableFuture<String> objectCompletableFuture = a1.thenCombine(a2, (a, b) -> {
return "12";
});
// 傳遞結果 無返回值
CompletableFuture<Void> voidCompletableFuture = a1.thenAcceptBoth(a2, (a, b) -> {
});
// 無入參 無返回值
a1.runAfterBoth(a2, ()->{
//
});
}CompletableFuture applyToEither / acceptEither / runAfterEither
三個方法都是將兩個CompletableFuture組合起來
但與上面不同的是只要其中一個執(zhí)行完了就會執(zhí)行某個任務,區(qū)別
applyToEither會將已經執(zhí)行完成的任務的執(zhí)行結果作為方法入參,并有返回值;acceptEither同樣將已經執(zhí)行完成的任務的執(zhí)行結果作為方法入參,但是沒有返回值;runAfterEither 沒有方法入參,也沒有返回值。
注意 兩個任務中只要有一個執(zhí)行異常,則將該異常信息作為指定任務的執(zhí)行結果
同時這些也提供了Async 異步方法
示例代碼:
@Test
public void justFor(){
CompletableFuture<Float> a1 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
CompletableFuture<Float> a2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 2.03f;
});
// 傳遞結果 有返回值
CompletableFuture<String> objectCompletableFuture = a1.thenCombine(a2, (a, b) -> {
return "12";
});
// 傳遞結果 無返回值
CompletableFuture<Void> voidCompletableFuture = a1.thenAcceptBoth(a2, (a, b) -> {
});
// 無入參 無返回值
a1.runAfterBoth(a2, ()->{
//
});
}
CompletableFuture thenCompose
thenCompose
- 在某個任務執(zhí)行完成后,將該任務的執(zhí)行結果作為方法入參然后執(zhí)行指定方法,該方法會返回一個新的CompletableFuture實例
- 如果該CompletableFuture實例的result不為null,則返回一個基于該result的新的CompletableFuture實例;
- 如果該CompletableFuture實例為null,則執(zhí)行這個新任務
同樣的提供Async方式
@Test
public void justFor(){
CompletableFuture<Float> a1 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
CompletableFuture<Float> a2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 2.03f;
});
// 傳遞結果 有返回值
CompletableFuture<String> objectCompletableFuture = a1.applyToEither(a2, (b) -> {
return "12";
});
// 傳遞結果 無返回值
CompletableFuture<Void> voidCompletableFuture = a1.acceptEither(a2, (b) -> {
});
// 無入參 無返回值
a1.runAfterEither(a2, ()->{
//
});
}
CompletableFuture 的 allOf() anyOf()
allOf返回的CompletableFuture是多個任務都執(zhí)行完成后才會執(zhí)行,只要有一個任務執(zhí)行異常,則返回的 CompletableFuture 執(zhí)行get方法時會拋出異常,如果都正常執(zhí)行,則get返回nullanyOf只要有一個任務執(zhí)行完成,無論是正常執(zhí)行或者執(zhí)行異常,都會執(zhí)行向下執(zhí)行
示例代碼:
@Test
public void justFor(){
CompletableFuture<Float> a1 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 1.03f;
});
CompletableFuture<Float> a2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Thread.currentThread() = " + Thread.currentThread());
return 2.03f;
});
// 傳遞結果 有返回值
CompletableFuture<String> objectCompletableFuture = a1.applyToEither(a2, (b) -> {
return "12";
});
// 傳遞結果 無返回值
CompletableFuture<Void> voidCompletableFuture = a1.acceptEither(a2, (b) -> {
});
// 無入參 無返回值
a1.runAfterEither(a2, ()->{
//
});
}
參考文章
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- Java?CompletableFuture實現多線程異步編排
- 詳解Java8?CompletableFuture的并行處理用法
- Java8 使用工廠方法supplyAsync創(chuàng)建CompletableFuture實例
- Java8 自定義CompletableFuture的原理解析
- Java8 CompletableFuture 異步執(zhí)行操作
- Java并發(fā) CompletableFuture異步編程的實現
- Java8新的異步編程方式CompletableFuture實現
- Java8 CompletableFuture詳解
- Java中的CompletableFuture原理與用法
相關文章
MyBatis-Plus更新對象時將字段值更新為null的四種常見方法
MyBatis-Plus 是一個 MyBatis 的增強工具,在簡化開發(fā)、提高效率方面表現非常出色,而,在使用 MyBatis-Plus 更新對象時,默認情況下是不會將字段值更新為 null 的,如果你需要將某些字段的值更新為 null,有幾種方法可以實現,本文將介紹幾種常見的方法2024-11-11
SpringCloud實戰(zhàn)之Feign聲明式服務調用
這篇文章主要介紹了SpringCloud實戰(zhàn)之Feign聲明式服務調用,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
創(chuàng)建SpringBoot工程并集成Mybatis的方法
這篇文章主要介紹了創(chuàng)建SpringBoot工程并集成Mybatis,需要的朋友可以參考下2018-06-06

