文章目录

  • 前言
  • 一、基础篇
    • 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教程相关推荐

  1. Java 8 CompletableFuture 教程

    Java 8 有大量的新特性和增强如 Lambda 表达式,Streams,CompletableFuture等.在本篇文章中我将详细解释清楚CompletableFuture以及它所有方法的使用. ...

  2. Java 8 CompletableFuture 教程 1

    Java 8 有大量的新特性和增强如 Lambda 表达式,Streams,CompletableFuture等.在本篇文章中我将详细解释清楚CompletableFuture以及它所有方法的使用. ...

  3. 用java实现combin函数_Java并发工具类CompletableFuture教程与示例

    Java 8带来了大量的新功能和增强功能,例如Lambda表达式,Streams,CompletableFutures等.在本文中,我将通过简单的示例向您详细说明CompletableFuture及其 ...

  4. 异步编程原理以及Java实现

    说实话多线程和异步是非常容易让人混淆的,好像产生的效果差不多,甚至有人称多线程为异步,实际上这两种技术背后的实现原理是不同的. 假设您有2个任务,不涉及任何IO(在多处理器机器上).在这种情况下,线程 ...

  5. Java常用知识补充

    Java常用知识补充 目录 Java常用知识补充 1.sort与comparator 1)Java的sort 2)Java 的Comparator 2.java lamda 3.java集合 Arra ...

  6. 一条数据的HBase之旅,简明HBase入门教程-Write全流程

    如果将上篇内容理解为一个冗长的"铺垫",那么,从本文开始,剧情才开始正式展开.本文基于提供的样例数据,介绍了写数据的接口,RowKey定义,数据在客户端的组装,数据路由,打包分发, ...

  7. Java 8 简明教程

    Java 8已于2014年3月18日正式发布了,新版本带来了诸多改进,包括Lambda表达式.Streams.日期时间API等等.本文就带你领略Java 8的全新特性. 本文由 ImportNew网站 ...

  8. 使用Reactor进行反应式编程最全教程

    反应式编程(Reactive Programming)这种新的编程范式越来越受到开发人员的欢迎.在 Java 社区中比较流行的是 RxJava 和 RxJava 2.本文要介绍的是另外一个新的反应式编 ...

  9. 关于CompletableFuture的一切,看这篇文章就够了

    文章目录 CompletableFuture作为Future使用 异步执行code 组合Futures thenApply() 和 thenCompose()的区别 并行执行任务 异常处理 java中 ...

最新文章

  1. 不是所有邮件服务器都叫智慧邮件系统
  2. 014_Redis的哨兵模式
  3. 我如何想成为Java
  4. 蓝桥杯省赛考点_【蓝桥杯单片机01】从历年决赛真题中寻找单片机常见的考点...
  5. echart 三维可视化地图_揭秘720°三维全景3D实景地图制作技术
  6. PATH与CLASSPATH的区别
  7. 【NVIDIA】显卡报错:NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver
  8. python 客户端同构_同构python算法
  9. 开发微信支付功能之微信限制金额说明
  10. 笔记本在Win7/Win8/win8.1下安装OS X 10.9.3懒人版通用教程
  11. --------------------------------------MYSQL批量修改字段类型---------------------------------
  12. 算法谜题——三个水壶问题
  13. Arduino驱动LM35温度传感器自制温度计
  14. 关于可控核聚变的想法
  15. BT.656接口速率
  16. ╮(╯▽╰)╭发现好难( ⊙ o ⊙ )啊!
  17. 如何用Python进行股票预测,数据分析带你从小白开始
  18. uni-app的发展历程
  19. [CSP-J 2022] 解密
  20. html全屏/退出全屏按钮,以及监听Esc退出后按钮样式变更

热门文章

  1. 团队作业3 需求改进与系统设计
  2. IDEA2019 Java连接PostgreSQL数据库实现基础功能增删改查
  3. C++ STL函数 结构体数组sort()排序(henu.hjy)
  4. 判断N!末尾有多少个0
  5. webStorm创建vue项目环境
  6. java语言程序设计(新手篇)
  7. python之不同公司不同年份同一财务指标比较
  8. SpringBoot整合最新Elasticsearch Java API Client 7.16教程
  9. listview简单应用之BaseAdapter(二)
  10. 使用Clang作为编译器 —— AddressSanitizer