CompletableFuture教程
文章目录
- 前言
- 一、基础篇
- 1、案例1_ CompletableFuture.supplyAsync()
- 1.1、需求
- 1.2、代码
- 1.3、总结
- 2、案例2_ CompletableFuture.thenCompose()
- 2.1、需求
- 2.2、代码
- 2.3、总结
- 3、案例3_ CompletableFuture.thenCombine()
- 3.1、需求
- 3.2、代码
- 3.3、总结
- 二、扩展篇
- 1、案例1_ CompletableFuture.thenApplyAsync()
- 1.1、需求
- 1.2、代码
- 1.3、总结
- 2、案例2_ CompletableFuture.applyToEither()
- 2.1、需求
- 2.2、代码
- 2.3、总结
- 3、案例3_ CompletableFuture.exceptionally()
- 3.1、需求
- 3.2、代码
- 3.2.1、没处理异常的代码:
- 3.2.2、处理了异常的代码:
- 3.3、总结
- 总结
前言
java程序员绕不开的就是高并发。而高并发系列中,无非就是异步、锁、多线程。今天要介绍的就是CompletableFuture。本人水平有限,如有误导,欢迎斧正,一起学习,共同进步!
一、基础篇
1、案例1_ CompletableFuture.supplyAsync()
1.1、需求
有三步骤,(名字相同的是同一个线程。小白是一个线程,厨师是一个线程):
1、小白点菜
2、厨师做菜
3、小白吃饭
1.2、代码
package com.zheng.sync;import com.zheng.util.SmallUtil;import java.util.concurrent.CompletableFuture;/*** @author: ZhengTianLiang* @date: 2022/04/26 21:59* @desc: CompletableFuture 基础篇_1* 1、小白点菜* 2、厨师做菜* 3、小白吃饭***/
public class CompletableFutureBasicOne {public static void main(String[] args) {SmallUtil.printTimeAndThread("小白进入餐厅");SmallUtil.printTimeAndThread("小白点了 番茄炒蛋 + 米饭");SmallUtil.printTimeAndThread("小白再打王者1");// jdk8的异步CompletableFuture<String > cf1 = CompletableFuture.supplyAsync(()->{SmallUtil.printTimeAndThread("厨师开始炒菜了");SmallUtil.sleepMillis(1000L);SmallUtil.printTimeAndThread("厨师开始打饭了");SmallUtil.sleepMillis(1000L);return "番茄炒蛋 + 米饭 做好了";});SmallUtil.printTimeAndThread("小白再打王者2");/*** cf1.join() 的结果集,就是 CompletableFuture的泛型的值,* cf1.join() 也会抛出异常*/SmallUtil.printTimeAndThread(String.format("%s,小白开吃了",cf1.join()));/*** 结果:* 2022-04-26 10:04:26 | 1 | main | 小白进入餐厅* 2022-04-26 10:04:26 | 1 | main | 小白点了 番茄炒蛋 + 米饭* 2022-04-26 10:04:26 | 1 | main | 小白再打王者1* 2022-04-26 10:04:26 | 1 | main | 小白再打王者2* 2022-04-26 10:04:26 | 12 | ForkJoinPool.commonPool-worker-9 | 厨师开始炒菜了* 2022-04-26 10:04:27 | 12 | ForkJoinPool.commonPool-worker-9 | 厨师开始打饭了* 2022-04-26 10:04:28 | 1 | main | 番茄炒蛋 + 米饭 做好了,小白开吃了*/}
}
1.3、总结
CompletableFuture.supplyAsync(() -> {return “”;})。supplyAsync 是支持返回值的异步;runAsync 不支持返回值的异步。
2、案例2_ CompletableFuture.thenCompose()
2.1、需求
1、小白点餐
2、厨师做饭
3、服务器送菜(这个需要在2的后面执行)
4、小白吃饭
2.2、代码
package com.zheng.sync;import com.zheng.util.SmallUtil;import java.util.concurrent.CompletableFuture;/*** @author: ZhengTianLiang* @date: 2022/04/26 22:32* @desc: CompletableFuture 基础篇_2* 1、小白点餐* 2、厨师做饭* 3、服务器送菜(这个需要在2的后面执行)* 4、小白吃饭*/
public class CompletableFutureBasicTwo {public static void main(String[] args) {SmallUtil.printTimeAndThread("小白进入餐厅");SmallUtil.printTimeAndThread("小白点了 番茄炒蛋 + 米饭");SmallUtil.printTimeAndThread("小白再打王者1");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("厨师开始炒菜了");SmallUtil.sleepMillis(1000L);return "番茄炒蛋";}).thenCompose(dist -> CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("服务员开始打饭了");SmallUtil.sleepMillis(1000L);return dist + "米饭";}));/*** thenCompose 这个方法中:是吧前面任务的结果,交给下一个任务* 1、dist 代表着前面那个线程的返回值,这里是 番茄炒蛋(String)* 2、 CompletableFuture.supplyAsync 代表着,里面的代码会在领一个线程中执行* 3、前一个任务完成,有结果以后,下一个任务才会触发*/SmallUtil.printTimeAndThread("小白再打王者2");SmallUtil.printTimeAndThread(String.format("%s,小白开吃了",cf1.join()));/*** 2022-04-26 10:04:17 | 1 | main | 小白进入餐厅* 2022-04-26 10:04:17 | 1 | main | 小白点了 番茄炒蛋 + 米饭* 2022-04-26 10:04:17 | 1 | main | 小白再打王者1* 2022-04-26 10:04:17 | 12 | ForkJoinPool.commonPool-worker-9 | 厨师开始炒菜了* 2022-04-26 10:04:17 | 1 | main | 小白再打王者2* 2022-04-26 10:04:19 | 12 | ForkJoinPool.commonPool-worker-9 | 服务员开始打饭了* 2022-04-26 10:04:20 | 1 | main | 番茄炒蛋米饭,小白开吃了*/}
}
2.3、总结
CompletableFuture.supplyAsync().thenCompose(); 这个thenCompose中的方法,是再第一个的后面执行的。
3、案例3_ CompletableFuture.thenCombine()
3.1、需求
1、小白点饭
2、厨师做饭
3、服务器蒸米饭 (2、3 是同事进行的,没有先后顺序)
4、小白吃饭
3.2、代码
package com.zheng.sync.basic;import com.zheng.util.SmallUtil;import java.util.concurrent.CompletableFuture;/*** @author: ZhengTianLiang* @date: 2022/04/26 22:58* @desc: CompletableFuture 基础篇_2* 1、小白点饭* 2、厨师做饭* 3、服务器蒸米饭 (2、3 是同事进行的,没有先后顺序)* 4、小白吃饭*/
public class CompletableFutureBasicThree {public static void main(String[] args) {SmallUtil.printTimeAndThread("小白进入餐厅");SmallUtil.printTimeAndThread("小白点了 番茄炒蛋 + 米饭");SmallUtil.printTimeAndThread("小白再打王者1");CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("厨师开始炒菜了");SmallUtil.sleepMillis(1000L);return "番茄炒蛋";}).thenCombine(CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("服务员开始蒸米饭了");SmallUtil.sleepMillis(1000L);return "米饭";}), (dish,rice) -> {SmallUtil.printTimeAndThread("服务员开始打饭了");SmallUtil.sleepMillis(1000L);return String.format("%s + %s 好了啊" ,dish,rice);} );/*** thenCombine 代表着,这俩异步任务是同时执行的,同时执行完了以后,再把他们加工成一个结果*/SmallUtil.printTimeAndThread("小白再打王者2");SmallUtil.printTimeAndThread(String.format("%s,小白开吃了",cf1.join()));/*** 2022-04-26 11:04:36 | 1 | main | 小白进入餐厅* 2022-04-26 11:04:36 | 1 | main | 小白点了 番茄炒蛋 + 米饭* 2022-04-26 11:04:36 | 1 | main | 小白再打王者1* 2022-04-26 11:04:36 | 12 | ForkJoinPool.commonPool-worker-9 | 厨师开始炒菜了* 2022-04-26 11:04:36 | 13 | ForkJoinPool.commonPool-worker-2 | 服务员开始蒸米饭了* 2022-04-26 11:04:36 | 1 | main | 小白再打王者2* 2022-04-26 11:04:37 | 13 | ForkJoinPool.commonPool-worker-2 | 服务员开始打饭了* 2022-04-26 11:04:38 | 1 | main | 番茄炒蛋 + 米饭 好了啊,小白开吃了*/}
}
3.3、总结
CompletableFuture.supplyAsync().thenCombine();这个thenCombine代表他们是同时执行的。
二、扩展篇
1、案例1_ CompletableFuture.thenApplyAsync()
1.1、需求
1、小白吃好了
2、小白结账 要发票
3、小白接到朋友电话,约定了一起打游戏
4、服务员收款
5、收银员开发票(注意,和上面的4,不是一个人)
6、小白收到发票,准备回家
1.2、代码
package com.zheng.sync.advance;import com.zheng.util.SmallUtil;import java.util.concurrent.CompletableFuture;/*** @author: ZhengTianLiang* @date: 2022/04/27 22:50* @desc: 另一种实现方式* 1、小白吃好了* 2、小白结账 要发票* 3、小白接到朋友电话,约定了一起打游戏* 4、服务员收款* 5、收银员开发票(注意,和上面的4,不是一个人)* 6、小白收到发票,准备回家*/
public class CompletableFutureAdvanceOne_2 {public static void main(String[] args) {SmallUtil.printTimeAndThread("小白吃好了");SmallUtil.printTimeAndThread("小白结账 要发票");
// CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() ->{
// SmallUtil.printTimeAndThread("服务员收款");
// SmallUtil.sleepMillis(1000L);
// return "服务员收款";
// }).thenApplyAsync(dist -> {
// SmallUtil.printTimeAndThread("收银员开发票");
// SmallUtil.sleepMillis(1000L);
// return "收银员开发票";
// } );CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("服务员收款 500元");SmallUtil.sleepMillis(1000L);return "500";}).thenApplyAsync(money -> {SmallUtil.printTimeAndThread(String.format("收银员开发票 %s" ,money));SmallUtil.sleepMillis(1000L);return String.format("收银员开发票 %s" ,money);});SmallUtil.printTimeAndThread("小白接到朋友电话,约定了一起打游戏");SmallUtil.printTimeAndThread(String.format("小白收到%s,准备回家",cf1.join()));/*** "C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" -javaagent:D:\java\ruanjian\idea\path\lib\idea_rt.jar=53062:D:\java\ruanjian\idea\path\bin -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;D:\java\ruanjian\idea\file\testcompletablefuture\target\classes;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter-web\2.6.7\spring-boot-starter-web-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter\2.6.7\spring-boot-starter-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot\2.6.7\spring-boot-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-autoconfigure\2.6.7\spring-boot-autoconfigure-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter-logging\2.6.7\spring-boot-starter-logging-2.6.7.jar;D:\java\ruanjian\maven\cangku\ch\qos\logback\logback-classic\1.2.11\logback-classic-1.2.11.jar;D:\java\ruanjian\maven\cangku\ch\qos\logback\logback-core\1.2.11\logback-core-1.2.11.jar;D:\java\ruanjian\maven\cangku\org\apache\logging\log4j\log4j-to-slf4j\2.17.2\log4j-to-slf4j-2.17.2.jar;D:\java\ruanjian\maven\cangku\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;D:\java\ruanjian\maven\cangku\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;D:\java\ruanjian\maven\cangku\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\java\ruanjian\maven\cangku\org\yaml\snakeyaml\1.29\snakeyaml-1.29.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter-json\2.6.7\spring-boot-starter-json-2.6.7.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\core\jackson-databind\2.13.2.1\jackson-databind-2.13.2.1.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\core\jackson-annotations\2.13.2\jackson-annotations-2.13.2.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\core\jackson-core\2.13.2\jackson-core-2.13.2.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.2\jackson-datatype-jdk8-2.13.2.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.2\jackson-datatype-jsr310-2.13.2.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.2\jackson-module-parameter-names-2.13.2.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter-tomcat\2.6.7\spring-boot-starter-tomcat-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\apache\tomcat\embed\tomcat-embed-core\9.0.62\tomcat-embed-core-9.0.62.jar;D:\java\ruanjian\maven\cangku\org\apache\tomcat\embed\tomcat-embed-el\9.0.62\tomcat-embed-el-9.0.62.jar;D:\java\ruanjian\maven\cangku\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.62\tomcat-embed-websocket-9.0.62.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-web\5.3.19\spring-web-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-beans\5.3.19\spring-beans-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-webmvc\5.3.19\spring-webmvc-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-aop\5.3.19\spring-aop-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-context\5.3.19\spring-context-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-expression\5.3.19\spring-expression-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\projectlombok\lombok\1.18.24\lombok-1.18.24.jar;D:\java\ruanjian\maven\cangku\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-core\5.3.19\spring-core-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-jcl\5.3.19\spring-jcl-5.3.19.jar" com.zheng.sync.advance.CompletableFutureAdvanceOne_2* 2022-05-04 10:05:16 | 1 | main | 小白吃好了* 2022-05-04 10:05:16 | 1 | main | 小白结账 要发票* 2022-05-04 10:05:16 | 12 | ForkJoinPool.commonPool-worker-9 | 服务员收款 500元* 2022-05-04 10:05:16 | 1 | main | 小白接到朋友电话,约定了一起打游戏* 2022-05-04 10:05:17 | 12 | ForkJoinPool.commonPool-worker-9 | 收银员开发票 500* 2022-05-04 10:05:18 | 1 | main | 小白收到收银员开发票 500,准备回家*/}
}
1.3、总结
CompletableFuture.supplyAsync() .thenApplyAsync();这个thenApplyAsync虽然有先后顺序,但是是俩个线程。
2、案例2_ CompletableFuture.applyToEither()
2.1、需求
1、小白吃完了,准备回家
2、小白在等车,哪个车先来,就做哪个车
2.2、代码
package com.zheng.sync.advance;import com.zheng.util.SmallUtil;import java.util.concurrent.CompletableFuture;/*** @author: ZhengTianLiang* @date: 2022/04/28 23:03* @desc: CompletableFuture扩展_2* 1、小白吃完了,准备回家* 2、小白在等车,哪个车先来,就做哪个车** todo: .applyToEither() 俩线程,谁先执行完,就把先执行完的结果返回给Future*/
public class CompletableFutureAdvanceTwo {public static void main(String[] args) {SmallUtil.printTimeAndThread("小白吃完了,准备回家");SmallUtil.printTimeAndThread("小白在等车");CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("70路公交来了");SmallUtil.sleepMillis(3000L);return "70路公交";}).applyToEither(CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("80路公交来了");SmallUtil.sleepMillis(2000L);return "80路公交";}),firstComeBus -> firstComeBus);/*** 2022-04-28 11:04:04 | 1 | main | 小白吃完了,准备回家* 2022-04-28 11:04:04 | 1 | main | 小白在等车* 2022-04-28 11:04:04 | 12 | ForkJoinPool.commonPool-worker-9 | 70路公交来了* 2022-04-28 11:04:04 | 13 | ForkJoinPool.commonPool-worker-2 | 80路公交来了* 2022-04-28 11:04:06 | 1 | main | 小白坐上了 80路公交*/SmallUtil.printTimeAndThread(String.format("小白坐上了 %s ",cf1.join()));}
}
2.3、总结
CompletableFuture.supplyAsync().applyToEither(); 中的applyToEither 代表着谁先来,就先执行谁
3、案例3_ CompletableFuture.exceptionally()
3.1、需求
1、小白吃完了,准备回家
2、小白在等车,哪个车先来,就做哪个车
3、假设小白做的是700路公交,然后700路公交路上没电了,然后小白打车回家
3.2、代码
3.2.1、没处理异常的代码:
package com.zheng.sync.advance;import com.zheng.util.SmallUtil;import java.util.concurrent.CompletableFuture;/*** @author: ZhengTianLiang* @date: 2022/05/04 9:45* @desc: 这个主要是处理,CompletableFutureAdvance 的异常处理* 1、小白吃完了,准备回家* 2、小白在等车,哪个车先来,就做哪个车* 3、假设小白做的是700路公交,然后700路公交路上没电了,然后小白打车回家*/
public class CompletableFutureAdvanceThree {public static void main(String[] args) {SmallUtil.printTimeAndThread("小白吃完了,准备回家");SmallUtil.printTimeAndThread("小白在等车");CompletableFuture<String> bus = CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("700路公交来了");SmallUtil.sleepMillis(1000L);return "700路公交";}).applyToEither(CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("800路公交来了");SmallUtil.sleepMillis(2000L);return "800路公交";}),firstComeBus -> {SmallUtil.printTimeAndThread("小白坐上了"+firstComeBus);if (firstComeBus.startsWith("700")){throw new RuntimeException("700路公交没电了");}return firstComeBus;});/*** 抛出一下异常:* Exception in thread "main" java.util.concurrent.CompletionException: java.lang.RuntimeException: 700路公交没电了* Caused by: java.lang.RuntimeException: 700路公交没电了* at com.zheng.sync.advance.CompletableFutureAdvanceThree.lambda$main$2(CompletableFutureAdvanceThree.java:32)*/SmallUtil.printTimeAndThread(String.format("%s,小白做车回家",bus.join()));}
}
3.2.2、处理了异常的代码:
package com.zheng.sync.advance;import com.zheng.util.SmallUtil;import java.util.concurrent.CompletableFuture;/*** @author: ZhengTianLiang* @date: 2022/05/04 9:45* @desc: 这个主要是处理,CompletableFutureAdvance 的异常处理* 1、小白吃完了,准备回家* 2、小白在等车,哪个车先来,就做哪个车* 3、假设小白做的是700路公交,然后700路公交路上没电了,然后小白打车回家* todo: 是为了处理,前面抛出的异常*/
public class CompletableFutureAdvanceThree_2 {public static void main(String[] args) {SmallUtil.printTimeAndThread("小白吃完了,准备回家");SmallUtil.printTimeAndThread("小白在等车");CompletableFuture<String> bus = CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("700路公交来了");SmallUtil.sleepMillis(1000L);return "700路公交";}).applyToEither(CompletableFuture.supplyAsync(() -> {SmallUtil.printTimeAndThread("800路公交来了");SmallUtil.sleepMillis(2000L);return "800路公交";}),firstComeBus -> {SmallUtil.printTimeAndThread("小白坐上了"+firstComeBus);if (firstComeBus.startsWith("700")){throw new RuntimeException("700路公交没电了");}return firstComeBus;}).exceptionally(e -> {SmallUtil.printTimeAndThread("进去了异常的方法"+e.getMessage());return "做了出租车";});/*** "C:\Program Files\Java\jdk1.8.0_161\bin\java.exe" -javaagent:D:\java\ruanjian\idea\path\lib\idea_rt.jar=50710:D:\java\ruanjian\idea\path\bin -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_161\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_161\jre\lib\rt.jar;D:\java\ruanjian\idea\file\testcompletablefuture\target\classes;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter-web\2.6.7\spring-boot-starter-web-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter\2.6.7\spring-boot-starter-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot\2.6.7\spring-boot-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-autoconfigure\2.6.7\spring-boot-autoconfigure-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter-logging\2.6.7\spring-boot-starter-logging-2.6.7.jar;D:\java\ruanjian\maven\cangku\ch\qos\logback\logback-classic\1.2.11\logback-classic-1.2.11.jar;D:\java\ruanjian\maven\cangku\ch\qos\logback\logback-core\1.2.11\logback-core-1.2.11.jar;D:\java\ruanjian\maven\cangku\org\apache\logging\log4j\log4j-to-slf4j\2.17.2\log4j-to-slf4j-2.17.2.jar;D:\java\ruanjian\maven\cangku\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;D:\java\ruanjian\maven\cangku\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;D:\java\ruanjian\maven\cangku\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\java\ruanjian\maven\cangku\org\yaml\snakeyaml\1.29\snakeyaml-1.29.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter-json\2.6.7\spring-boot-starter-json-2.6.7.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\core\jackson-databind\2.13.2.1\jackson-databind-2.13.2.1.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\core\jackson-annotations\2.13.2\jackson-annotations-2.13.2.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\core\jackson-core\2.13.2\jackson-core-2.13.2.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.2\jackson-datatype-jdk8-2.13.2.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.2\jackson-datatype-jsr310-2.13.2.jar;D:\java\ruanjian\maven\cangku\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.2\jackson-module-parameter-names-2.13.2.jar;D:\java\ruanjian\maven\cangku\org\springframework\boot\spring-boot-starter-tomcat\2.6.7\spring-boot-starter-tomcat-2.6.7.jar;D:\java\ruanjian\maven\cangku\org\apache\tomcat\embed\tomcat-embed-core\9.0.62\tomcat-embed-core-9.0.62.jar;D:\java\ruanjian\maven\cangku\org\apache\tomcat\embed\tomcat-embed-el\9.0.62\tomcat-embed-el-9.0.62.jar;D:\java\ruanjian\maven\cangku\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.62\tomcat-embed-websocket-9.0.62.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-web\5.3.19\spring-web-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-beans\5.3.19\spring-beans-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-webmvc\5.3.19\spring-webmvc-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-aop\5.3.19\spring-aop-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-context\5.3.19\spring-context-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-expression\5.3.19\spring-expression-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\projectlombok\lombok\1.18.24\lombok-1.18.24.jar;D:\java\ruanjian\maven\cangku\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-core\5.3.19\spring-core-5.3.19.jar;D:\java\ruanjian\maven\cangku\org\springframework\spring-jcl\5.3.19\spring-jcl-5.3.19.jar" com.zheng.sync.advance.CompletableFutureAdvanceThree_2* 2022-05-04 09:05:36 | 1 | main | 小白吃完了,准备回家* 2022-05-04 09:05:36 | 1 | main | 小白在等车* 2022-05-04 09:05:36 | 12 | ForkJoinPool.commonPool-worker-9 | 700路公交来了* 2022-05-04 09:05:36 | 13 | ForkJoinPool.commonPool-worker-2 | 800路公交来了* 2022-05-04 09:05:37 | 12 | ForkJoinPool.commonPool-worker-9 | 小白坐上了700路公交* 2022-05-04 09:05:37 | 12 | ForkJoinPool.commonPool-worker-9 | 进去了异常的方法java.lang.RuntimeException: 700路公交没电了* 2022-05-04 09:05:37 | 1 | main | 做了出租车,小白做车回家** Process finished with exit code 0*/SmallUtil.printTimeAndThread(String.format("%s,小白做车回家",bus.join()));}
}
3.3、总结
CompletableFuture bus = CompletableFuture.supplyAsync(() -> {return “700路公交”;})
.applyToEither(CompletableFuture.supplyAsync(() -> {return “800路公交”;}),
firstComeBus -> {throw new RuntimeException(“700路公交没电了”);}return firstComeBus;})
.exceptionally(e -> {return “做了出租车”;}); 其中,exceptionally 可以写在中间,最后,等任意位置,代表着处理异常
总结
下面这张图是我自己学习的时候的一些总结,希望能对读者有一些帮助。
CompletableFuture教程相关推荐
- Java 8 CompletableFuture 教程
Java 8 有大量的新特性和增强如 Lambda 表达式,Streams,CompletableFuture等.在本篇文章中我将详细解释清楚CompletableFuture以及它所有方法的使用. ...
- Java 8 CompletableFuture 教程 1
Java 8 有大量的新特性和增强如 Lambda 表达式,Streams,CompletableFuture等.在本篇文章中我将详细解释清楚CompletableFuture以及它所有方法的使用. ...
- 用java实现combin函数_Java并发工具类CompletableFuture教程与示例
Java 8带来了大量的新功能和增强功能,例如Lambda表达式,Streams,CompletableFutures等.在本文中,我将通过简单的示例向您详细说明CompletableFuture及其 ...
- 异步编程原理以及Java实现
说实话多线程和异步是非常容易让人混淆的,好像产生的效果差不多,甚至有人称多线程为异步,实际上这两种技术背后的实现原理是不同的. 假设您有2个任务,不涉及任何IO(在多处理器机器上).在这种情况下,线程 ...
- Java常用知识补充
Java常用知识补充 目录 Java常用知识补充 1.sort与comparator 1)Java的sort 2)Java 的Comparator 2.java lamda 3.java集合 Arra ...
- 一条数据的HBase之旅,简明HBase入门教程-Write全流程
如果将上篇内容理解为一个冗长的"铺垫",那么,从本文开始,剧情才开始正式展开.本文基于提供的样例数据,介绍了写数据的接口,RowKey定义,数据在客户端的组装,数据路由,打包分发, ...
- Java 8 简明教程
Java 8已于2014年3月18日正式发布了,新版本带来了诸多改进,包括Lambda表达式.Streams.日期时间API等等.本文就带你领略Java 8的全新特性. 本文由 ImportNew网站 ...
- 使用Reactor进行反应式编程最全教程
反应式编程(Reactive Programming)这种新的编程范式越来越受到开发人员的欢迎.在 Java 社区中比较流行的是 RxJava 和 RxJava 2.本文要介绍的是另外一个新的反应式编 ...
- 关于CompletableFuture的一切,看这篇文章就够了
文章目录 CompletableFuture作为Future使用 异步执行code 组合Futures thenApply() 和 thenCompose()的区别 并行执行任务 异常处理 java中 ...
最新文章
- 不是所有邮件服务器都叫智慧邮件系统
- 014_Redis的哨兵模式
- 我如何想成为Java
- 蓝桥杯省赛考点_【蓝桥杯单片机01】从历年决赛真题中寻找单片机常见的考点...
- echart 三维可视化地图_揭秘720°三维全景3D实景地图制作技术
- PATH与CLASSPATH的区别
- 【NVIDIA】显卡报错:NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver
- python 客户端同构_同构python算法
- 开发微信支付功能之微信限制金额说明
- 笔记本在Win7/Win8/win8.1下安装OS X 10.9.3懒人版通用教程
- --------------------------------------MYSQL批量修改字段类型---------------------------------
- 算法谜题——三个水壶问题
- Arduino驱动LM35温度传感器自制温度计
- 关于可控核聚变的想法
- BT.656接口速率
- ╮(╯▽╰)╭发现好难( ⊙ o ⊙ )啊!
- 如何用Python进行股票预测,数据分析带你从小白开始
- uni-app的发展历程
- [CSP-J 2022] 解密
- html全屏/退出全屏按钮,以及监听Esc退出后按钮样式变更
热门文章
- 团队作业3 需求改进与系统设计
- IDEA2019 Java连接PostgreSQL数据库实现基础功能增删改查
- C++ STL函数 结构体数组sort()排序(henu.hjy)
- 判断N!末尾有多少个0
- webStorm创建vue项目环境
- java语言程序设计(新手篇)
- python之不同公司不同年份同一财务指标比较
- SpringBoot整合最新Elasticsearch Java API Client 7.16教程
- listview简单应用之BaseAdapter(二)
- 使用Clang作为编译器 —— AddressSanitizer