Java8异步类CompletableFuture详解

1、前言

学习java基础时候多线程使用我们首先学习的 RunableFutureThreadExecutorServiceCallable等相关类,在我们日常工作或者学习中有些场景并不满足我们需求,JDK8引入了一个新的类 CompletableFuture 来解决之前得问题, CompletableFuture 实现了 Future 接口和 CompletionStage 。因此 CompletableFuture是对 Futrue的功能增强包含了Future的功能。从继承的另一个 CompletionStage 的名称来看完成阶段性的接口,接下来了解一下 CompletableFuture 的一些基本情况以及使用和注意事项。

2、CompletableFuture使用

CompletableFuture提供了几十种方法,辅助我们的异步任务场景。这些方法包括创建异步任务、任务异步回调、多个任务组合处理等方面,JDK8设计出CompletableFuture。CompletableFuture提供了一种观察者模式类似的机制,可以让任务执行完成后通知监听的一方。

自定义线城池,一下代码都会使用到


   static ExecutorService executor = Executors.newFixedThreadPool(3, new ThreadFactory() {
        int count = 1;

        @Override
        public Thread newThread(Runnable runnable) {
            return new Thread(runnable, "completableFuture-executor-" + count++);
        }
    });

2.1创建异步任务

  • runAsync 用于构建一个没有入参也没有出参的任务;

  • supplyAsync 用于构建一个没有入参但是有出参的任务

    runAsync和supplyAsync可以指定线程池,如果不指定,则使用ForkJoinPool的commonPool线程池

    先看源码

public static  CompletableFuture supplyAsync(Supplier supplier) {
        return asyncSupplyStage(asyncPool, supplier);
    }

    public static  CompletableFuture supplyAsync(Supplier supplier,
                                                       Executor executor) {
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }

    public static CompletableFuture runAsync(Runnable runnable) {
        return asyncRunStage(asyncPool, runnable);
    }

    public static CompletableFuture runAsync(Runnable runnable,
                                                   Executor executor) {
        return asyncRunStage(screenExecutor(executor), runnable);
    }

runAsync执行CompletableFuture任务,没有返回值。

    /**
     * runAsync执行CompletableFuture任务,没有返回值。
     */
    public static void runAsyncExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束");

        });
        System.out.println("异步线程执行状态" + completableFuture.isDone());
        System.out.println("主线程正在执行");
        System.out.println("异步线程执行状态" + completableFuture.isDone());
        System.out.println(completableFuture.get());
    }

执行结果

异步线程执行状态false
completableFuture-当前线程名称:ForkJoinPool.commonPool-worker-9
异步线程执行执行结束
null

supplyAsync执行CompletableFuture任务,支持返回值-使用自定义线城池

public static void supplyAsyncExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
            System.out.println("异步线程执行执行结束");
            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------supplyAsyncExample-----正在执行");
        System.out.println(completableFuture.join());
        executor.shutdown(); // 线程池需要关闭
    }

执行结果

主线程-------supplyAsyncExample-----正在执行
completableFuture2-当前线程名称:completableFuture-executor-1
异步线程执行执行结束
msg-异步线程执行结束

2.2任务异步回调

2.2.1 thenRun/thenRunAsync

不关心上一个任务的执行返回结果,无参数,无返回值

CompletableFuture的thenRun方法,通俗点讲就是,做完第一个任务后,再做第二个任务。某个任务执行完成后,执行回调方法;但是前后两个任务没有参数传递,第二个任务也没有返回值

如果你执行第一个任务的时候,传入了一个自定义线程池:

  • 调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池
  • 调用thenRunAsync执行第二个任务时,则第一个任务使用的是你自己传入的线程池,第二个任务使用的是ForkJoin线程池
public CompletableFuture thenRun(Runnable action);
public CompletableFuture thenRunAsync(Runnable action);

thenRun代码

   public static void thenRunExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束,当前线程"+Thread.currentThread().getName());
            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------thenRunExample-----正在执行1");
        CompletableFuture voidCompletableFuture = completableFuture.thenRun(() -> {
            System.out.println("thenRunExample----正在执行第二个任务,当前线程"+Thread.currentThread().getName());
        });
        System.out.println("主线程-------thenRunExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线程池需要关闭

    }

执行结果

主线程-------thenRunExample-----正在执行1
主线程-------thenRunExample-----正在执行2
异步线程执行执行结束,当前线程completableFuture-executor-1
thenRunExample----正在执行第二个任务,当前线程completableFuture-executor-1
null

thenRunAsync代码-异步使用自定义线城池

  public static void thenRunAsyncExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束---当前线城"+Thread.currentThread().getName());
            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------thenRunAsyncExample-----正在执行1");
        CompletableFuture voidCompletableFuture = completableFuture.thenRunAsync(() -> {
            System.out.println("thenRunExample----正在执行第二个任务---当前线城"+Thread.currentThread().getName());
        });
        System.out.println("主线程-------thenRunAsyncExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线程池需要关闭

    }

执行结果

主线程-------thenRunAsyncExample-----正在执行1
主线程-------thenRunAsyncExample-----正在执行2
异步线程执行执行结束---当前线城completableFuture-executor-1
thenRunExample----正在执行第二个任务---当前线城ForkJoinPool.commonPool-worker-9
null

2.2.2.thenAccept/thenAcceptAsync

第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,但是回调方法是没有返回值的。

thenAccept代码示例

   public static void thenAcceptExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束--执行线程" + Thread.currentThread().getName());
            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------thenAcceptExample-----正在执行1");
        CompletableFuture voidCompletableFuture = completableFuture.thenAccept((msg) -> {
            System.out.println("thenAccept接受上一步返回参数" + msg);
            System.out.println("thenAcceptExample----正在执行第二个任务--执行线程" + Thread.currentThread().getName());
        });
        System.out.println("主线程-------thenAcceptExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线程池需要关闭
    }

执行结果

主线程-------thenAcceptExample-----正在执行1
主线程-------thenAcceptExample-----正在执行2
异步线程执行执行结束--执行线程completableFuture-executor-1
thenAccept接受上一步返回参数msg-异步线程执行结束
thenAcceptExample----正在执行第二个任务--执行线程completableFuture-executor-1
null

thenAcceptAsync代码示例

 public static void thenAcceptAsyncExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束---执行线程" + Thread.currentThread().getName());
            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------thenAcceptExample-----正在执行1");
        CompletableFuture voidCompletableFuture = completableFuture.thenAcceptAsync((msg) -> {
            System.out.println("thenAccept接受上一步返回参数" + msg);
            System.out.println("thenAcceptExample----正在执行第二个任务---执行线程" + Thread.currentThread().getName());
        }, executor);
        System.out.println("主线程-------thenAcceptExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线程池需要关闭

    }

运行结果

主线程-------thenAcceptExample-----正在执行1
主线程-------thenAcceptExample-----正在执行2
异步线程执行执行结束---执行线程completableFuture-executor-1
thenAccept接受上一步返回参数msg-异步线程执行结束
thenAcceptExample----正在执行第二个任务---执行线程completableFuture-executor-2
null
2.2.3 thenApply/thenApplyAsync

第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,并且回调方法是有返回值的

thenApply-不关心上一个任务的执行返回结果,有参数,有返回值-

代码

public static void thenApplyExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束---当前线程"+ Thread.currentThread().getName());

            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------thenApplyExample-----正在执行1");
        CompletableFuture voidCompletableFuture = completableFuture.thenApply((msg) -> {
            System.out.println("thenApply接受上一步返回参数" + msg);
            System.out.println("thenApplyExample----正在执行第二个任务----当前线程"+ Thread.currentThread().getName());

            return "thenApplyExample执行任务结束";
        });
        System.out.println("主线程-------thenApplyExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线池需要关闭
    }

执行结果

主线程-------thenApplyExample-----正在执行1
主线程-------thenApplyExample-----正在执行2
异步线程执行执行结束---当前线程completableFuture-executor-1
thenApply接受上一步返回参数msg-异步线程执行结束
thenApplyExample----正在执行第二个任务----当前线程completableFuture-executor-1
thenApplyExample执行任务结束

thenApplyAsync-任务异步回调-不关心上一个任务的执行返回结果,有参数,有返回值-

 public static void thenApplyAsyncExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束");
            System.out.println("当前线程名称:" + Thread.currentThread().getName());
            return "msg-异步线程执行结束";
        }, executor);
        System.out.println("主线程-------thenApplyAsyncExample-----正在执行1");
        CompletableFuture voidCompletableFuture = completableFuture.thenApplyAsync((msg) -> {
            System.out.println("thenApply接受上一步返回参数" + msg);
            System.out.println("当前线程名称:" + Thread.currentThread().getName());

            System.out.println("thenApplyAsyncExample----正在执行第二个任务");
            return "thenApplyAsyncExample执行任务结束";
        });
        System.out.println("主线程-------thenApplyAsyncExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线池需要关闭

    }

执行结果

主线程-------thenApplyAsyncExample-----正在执行1
主线程-------thenApplyAsyncExample-----正在执行2
异步线程执行执行结束
当前线程名称:completableFuture-executor-1
thenApply接受上一步返回参数msg-异步线程执行结束
当前线程名称:ForkJoinPool.commonPool-worker-9
thenApplyAsyncExample----正在执行第二个任务
thenApplyAsyncExample执行任务结束

2.2.4 exceptionally-

某个任务执行异常时,执行的回调方法;并且有抛出异常作为参数,传递到回调方法。

执行代码

 public static void exceptionallyExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("当前线程名称:" + Thread.currentThread().getName());
            throw new RuntimeException("咳咳!执行异常啦");
        }, executor);
        System.out.println("主线程-------exceptionallyExample-----正在执行1");

        CompletableFuture voidCompletableFuture = completableFuture.exceptionally((throwable) -> {
            System.out.println("当前线程名称:" + Thread.currentThread().getName());
            System.out.println("exceptionallyExample----发生异常信息----" + throwable.getMessage());
            return "handleExample执行结束";
        });
        System.out.println("主线程-------exceptionallyExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线池需关闭
    }

执行结果

主线程-------exceptionallyExample-----正在执行1
主线程-------exceptionallyExample-----正在执行2
当前线程名称:completableFuture-executor-1
当前线程名称:completableFuture-executor-1
exceptionallyExample----发生异常信息----java.lang.RuntimeException: 咳咳!执行异常啦
handleExample执行结束

2.2.5whenComplete/handle

whenComplete:某个任务执行完成后,执行的回调方法,无返回值;并且whenComplete方法返回的CompletableFuture的result是上个任务的结果
handle:任务执行完成后,执行回调方法,并且是有返回值的;并且handle方法返回的CompletableFuture的result是回调方法执行的结果。

whenComplete 代码示例

 public static void whenCompleteExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束--当前线程名称:" + Thread.currentThread().getName());
            return "msg-异步线程执行结束666";
        }, executor);
        System.out.println("主线程-------whenCompleteExample-----正在执行1");

        CompletableFuture voidCompletableFuture = completableFuture.whenComplete((msg, throwable) -> {
            System.out.println("当前线程名称:" + Thread.currentThread().getName());
            System.out.println("whenCompleteExample----接受参数" + msg);
        });
        System.out.println("主线程-------whenCompleteExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线池需要关闭
    }

执行结果

主线程-------whenCompleteExample-----正在执行1
主线程-------whenCompleteExample-----正在执行2
异步线程执行执行结束--当前线程名称:completableFuture-executor-1
当前线程名称:completableFuture-executor-1
whenCompleteExample----接受参数msg-异步线程执行结束666
msg-异步线程执行结束666

Handle 代码示例

  public static void handleExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步线程执行执行结束");
            System.out.println("当前线程名称:" + Thread.currentThread().getName());
            return "msg-异步线程执行结束666";
        }, executor);
        System.out.println("主线程-------handleExample-----正在执行1");

        CompletableFuture voidCompletableFuture = completableFuture.handle((msg, throwable) -> {
            System.out.println("当前线程名称:" + Thread.currentThread().getName());
            System.out.println("handleExample----接受参数" + msg);
            return "handleExample执行结束";
        });
        System.out.println("主线程-------handleExample-----正在执行2");
        System.out.println(voidCompletableFuture.get());
        executor.shutdown(); // 线池需要关闭

    }

执行结果

主线程-------handleExample-----正在执行1
主线程-------handleExample-----正在执行2
异步线程执行执行结束
当前线程名称:completableFuture-executor-1
当前线程名称:completableFuture-executor-1
handleExample----接受参数msg-异步线程执行结束666
handleExample执行结束

2.3 多个任务组合处理

2.3.1 thenCombine / thenAcceptBoth / runAfterBoth----AND组合关系

将两个CompletableFuture组合起来,只有这两个都正常执行完了,才会执行某个任务

区别在于:

  • thenCombine:会将两个任务的执行结果作为方法入参,传递到指定方法中,且有返回值

  • thenAcceptBoth: 会将两个任务的执行结果作为方法入参,传递到指定方法中,且无返回值

  • runAfterBoth 不会把执行结果当做方法入参,且没有返回值。

    thenCombine代码示列

public static void thenCombineExample() throws ExecutionException, InterruptedException {
    CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(1001);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());
        return "当前线程1执行结束";
    }, executor);
    CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(1001);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
        return "当前线程2执行结束";
    }, executor).thenCombine(completableFuture1, (msg1, msg2) -> {
        System.out.println("completableFuture1返回结果----" + msg1);
        System.out.println("completableFuture2返回结果----" + msg2);
        return "所有线程执行结束";

    });
    System.out.println("主线程-------thenCombineExample-----正在执行2");
    System.out.println(completableFuture2.join());
    executor.shutdown(); // 线池需关闭
}

执行结果

主线程-------thenCombineExample-----正在执行2
completableFuture1-当前线程名称:completableFuture-executor-1
completableFuture2-当前线程名称:completableFuture-executor-2
completableFuture1返回结果----当前线程2执行结束
completableFuture2返回结果----当前线程1执行结束
所有线程执行结束

thenAcceptBoth代码示例

 public static void thenAcceptBothExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程1执行结束";
        });
        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程2执行结束";
        }).thenAcceptBoth(completableFuture1, (msg1, msg2) -> {
            System.out.println("completableFuture1返回结果----" + msg1);
            System.out.println("completableFuture2返回结果----" + msg2);

        });
        System.out.println("主线程-------thenAcceptBothExample-----正在执行2");
        System.out.println(completableFuture2.join());
        executor.shutdown(); // 线池需关闭
    }

运行结果

主线程-------thenAcceptBothExample-----正在执行2
completableFuture1-当前线程名称:ForkJoinPool.commonPool-worker-9
completableFuture2-当前线程名称:ForkJoinPool.commonPool-worker-2
completableFuture1返回结果----当前线程2执行结束
completableFuture2返回结果----当前线程1执行结束
null

runAfterBoth代码示例

public static void runAfterBothExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程1执行结束";
        });
        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程2执行结束";
        }).runAfterBoth(completableFuture1, () -> {
            System.out.println("两个线程都执行结束啦----");

        });
        System.out.println("主线程-------runAfterBothExample-----正在执行2");
        System.out.println(completableFuture2.join());
        executor.shutdown(); // 线池需关闭
    }

运行结果

主线程-------runAfterBothExample-----正在执行2
completableFuture2-当前线程名称:ForkJoinPool.commonPool-worker-2
completableFuture1-当前线程名称:ForkJoinPool.commonPool-worker-9
两个线程都执行结束啦----
null

2.3.2 applyToEither / acceptEither / runAfterEither ----OR组合关系

将两个CompletableFuture组合起来,只要其中一个执行完了,就会执行某个任务。

区别在于:

  • applyToEither:会将已经执行完成的任务,作为方法入参,传递到指定方法中,且有返回值
  • acceptEither: 会将已经执行完成的任务,作为方法入参,传递到指定方法中,且无返回值
  • runAfterEither:不会把执行结果当做方法入参,且没有返回值。

applyToEither代码示例

public static void applyToEitherExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(101);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程1执行结束";
        });
        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(10001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程2执行结束";
        }).applyToEither(completableFuture1, msg -> {
            return msg;
        });
        System.out.println("主线程-------thenCombineExample-----正在执行2");
        System.out.println(completableFuture2.join());
        executor.shutdown(); // 线池需关闭
    }

执行结果

主线程-------thenCombineExample-----正在执行2
completableFuture1-当前线程名称:ForkJoinPool.commonPool-worker-9
当前线程1执行结束

acceptEither代码示例

  public static void acceptEitherExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程1执行结束";
        });
        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(10001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程2执行结束";
        }).acceptEither(completableFuture1, msg -> {
            System.out.println("获取某线程返回参数------" + msg);
        });
        System.out.println("主线程-------acceptEitherExample-----正在执行2");
        System.out.println(completableFuture2.join());
        executor.shutdown(); // 线池需关闭
    }

执行结果

主线程-------acceptEitherExample-----正在执行2
completableFuture1-当前线程名称:ForkJoinPool.commonPool-worker-9
获取某线程返回参数------当前线程1执行结束
null

2.3.3AllOf/AnyOf 多个任务组合处理

3AllOf:所有任务都执行完成后,才执行 allOf返回的CompletableFuture。如果任意一个任务异常,allOf的CompletableFuture,执行get方法,会抛出异常

AnyOf:任意一个任务执行完,就执行anyOf返回的CompletableFuture。如果执行的任务异常,anyOf的CompletableFuture,执行get方法,会抛出异常

AllOf代码示例

/**
     * 多个任务组合处理
     * 所有任务都执行完成后,才执行 allOf返回的CompletableFuture。如果任意一个任务异常,allOf的CompletableFuture,执行get方法,会抛出异常     *
     *
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public static void allOfExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程1执行结束";
        });
        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
//            throw new RuntimeException("咳咳!执行异常啦");
            return "当前线程2执行结束";

        });
        CompletableFuture completableFuture = CompletableFuture.allOf(completableFuture1, completableFuture2).whenComplete((msg1, msg2) -> {
            System.out.println("allOf----所有线程执行结束---" + msg1);
            System.out.println("allOf----所有线程执行结束---" + msg2);
        });
        System.out.println("主线程-------acceptEitherExample-----正在执行2");
        System.out.println(completableFuture.get());
    }

执行结果

主线程-------acceptEitherExample-----正在执行2
completableFuture1-当前线程名称:ForkJoinPool.commonPool-worker-9
completableFuture2-当前线程名称:ForkJoinPool.commonPool-worker-2
allOf----所有线程执行结束---null
allOf----所有线程执行结束---null
null

AnyOf代码示例

 public static void anyOfExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程1执行结束";
        });
        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1001);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程2执行结束";
        });
        CompletableFuture completableFuture = CompletableFuture.anyOf(completableFuture1, completableFuture2).whenComplete((msg1, msg2) -> {
            System.out.println("anyOf----所有线程执行结束---" + msg1);
            System.out.println("anyOf----所有线程执行结束---" + msg2);

        });
        System.out.println("主线程-------anyOfExample-----正在执行2");
        System.out.println(completableFuture.get());
    }
 
  

运行结果

主线程-------anyOfExample-----正在执行2
completableFuture1-当前线程名称:ForkJoinPool.commonPool-worker-9
completableFuture2-当前线程名称:ForkJoinPool.commonPool-worker-2
anyOf----所有线程执行结束---当前线程1执行结束
anyOf----所有线程执行结束---null
当前线程1执行结束

2.3.4thenCompose

thenCompose方法会在某个任务执行完成后,将该任务的执行结果,作为方法入参,去执行指定的方法。该方法会返回一个新的CompletableFuture实例

是对另一个CompletableFuture进行计算、操作,也就是说用来连接两个CompletableFuture,是生成一个新的CompletableFuture。

代码示例

   public static void thenComposeExample() throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(() -> {

            System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());
            return "当前线程1执行结束";
        },executor).thenCompose(result -> CompletableFuture.supplyAsync(() -> {
            System.out.println(result + "当前线程2执行结束-当前线程名称:" + Thread.currentThread().getName());
            return result + "当前线程2执行结束";
        },executor));

        System.out.println(completableFuture1.get());
    }

执行结果

completableFuture1-当前线程名称:completableFuture-executor-1
当前线程1执行结束当前线程2执行结束-当前线程名称:completableFuture-executor-2
当前线程1执行结束当前线程2执行结束

你可能感兴趣的:(【Java】,【工具】,java,开发语言)