很多时候多个任务之间的业务逻辑上处理存在串行[依赖]、并行、聚合的关系。CompletableFuture是Future接口的增强,实现了对任务的编排能力。
image.png
CompletionStage接口:执行某一个阶段,可向下执行后续阶段。
使用demo:

  1. CompletableFuture<String> future =CompletableFuture.supplyAsync(()‐>{
  2. System.out.println("执行有返回值的异步任务");
  3. try {
  4. Thread.sleep(5000);
  5. } catch (InterruptedException e) {
  6. e.printStackTrace();
  7. }
  8. return "Hello World";
  9. });
  10. //join()和get()方法都是用来获取CompletableFuture异步之后的返回值
  11. String result=future.get();
  12. System.out.println(result);
  13. //当CompletableFuture的计算结果完成,可以执行特定的 Action。
  14. future.whenComplete(new BiConsumer<String, Throwable>() {
  15. @Override
  16. public void accept(String t, Throwable action) {
  17. System.out.println(t+" 执行完成!");
  18. }
  19. });
  20. //抛出异常的时候,可以执行特定的Action。
  21. future.exceptionally(new Function<Throwable, String>() {
  22. @Override
  23. public String apply(Throwable t) {
  24. System.out.println("执行失败:"+t.getMessage());
  25. return "异常xxxx";
  26. }
  27. }).join();

应用场景

依赖关系:

  • thenApply() 把前面异步任务的结果,交给后面的Function
  • thenCompose()用来连接两个有依赖关系的任务,结果由第二个任务返回

    and聚合关系:

  • thenCombine:任务合并,有返回值

  • thenAccepetBoth:两个任务执行完成后,将结果交给thenAccepetBoth消耗,无返回值。
  • runAfterBoth:两个任务都执行完成后,执行下一步操作(Runnable)。

    or聚合关系:

  • applyToEither:两个任务谁执行的快,就使用那一个结果,有返回值。

  • acceptEither: 两个任务谁执行的快,就消耗那一个结果,无返回值。
  • runAfterEither: 任意一个任务执行完成,进行下一步操作(Runnable)。

    并行执行:

    CompletableFuture类自己也提供了anyOf()和allOf()用于支持多个CompletableFuture 并行执行

image.png

使用案例:实现最优的“烧水泡茶”程序

image.png
对于烧水泡茶这个程序,一种最优的分工方案:用两个线程 T1 和 T2 来完成烧水泡茶程序, T1 负责洗水壶、烧开水、泡茶这三道工序,T2 负责洗茶壶、洗茶杯、拿茶叶三道工序,其中 T1 在执行泡茶这道工序时需要等待 T2 完成拿茶叶的工序。

  1. public class CompletableFutureDemo2 {
  2. public static void main(String[] args) {
  3. //任务1:洗水壶‐>烧开水
  4. CompletableFuture<Void> f1=CompletableFuture.runAsync(() ‐>{
  5. System.out.println("T1:洗水壶...");
  6. sleep(1, TimeUnit.SECONDS);
  7. System.out.println("T1:烧开水...");
  8. sleep(15, TimeUnit.SECONDS);
  9. });
  10. //任务2:洗茶壶‐>洗茶杯‐>拿茶叶
  11. CompletableFuture<String> f2=CompletableFuture.supplyAsync(() ‐> {
  12. System.out.println("T2:洗茶壶...");
  13. sleep(1, TimeUnit.SECONDS);
  14. System.out.println("T2:洗茶杯...");
  15. sleep(2, TimeUnit.SECONDS);
  16. System.out.println("T2:拿茶叶...");
  17. sleep(1, TimeUnit.SECONDS);
  18. return "龙井";
  19. });
  20. //任务3:任务1和任务2完成后执行:泡茶
  21. CompletableFuture<String> f3 = f1.thenCombine(f2, (__, tf)‐>{
  22. System.out.println("T1:拿到茶叶:"+tf);
  23. System.out.println("T1:泡茶...");
  24. return "上茶:"+tf;
  25. });
  26. //等待任务3执行结果
  27. System.out.println(f3.join());
  28. }