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;@Overridepublic Thread newThread(Runnable runnable) {return new Thread(runnable, "completableFuture-executor-" + count++);}});

2.1创建异步任务

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

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

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

    先看源码

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {return asyncSupplyStage(asyncPool, supplier);}public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor) {return asyncSupplyStage(screenExecutor(executor), supplier);}public static CompletableFuture<Void> runAsync(Runnable runnable) {return asyncRunStage(asyncPool, runnable);}public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor) {return asyncRunStage(screenExecutor(executor), runnable);}

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

    /*** runAsync执行CompletableFuture任务,没有返回值。*/public static void runAsyncExample() throws ExecutionException, InterruptedException {CompletableFuture<Void> 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<String> 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<Void> thenRun(Runnable action);
public CompletableFuture<Void> thenRunAsync(Runnable action);

thenRun代码

   public static void thenRunExample() throws ExecutionException, InterruptedException {CompletableFuture<String> 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<Void> 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<String> 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<Void> 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<String> 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<Void> 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<String> 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<Void> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1001);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());return "当前线程1执行结束";}, executor);CompletableFuture<String> 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<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1001);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());return "当前线程1执行结束";});CompletableFuture<Void> 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<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1001);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());return "当前线程1执行结束";});CompletableFuture<Void> 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<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(101);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());return "当前线程1执行结束";});CompletableFuture<String> 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<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1001);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());return "当前线程1执行结束";});CompletableFuture<Void> 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<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1001);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());return "当前线程1执行结束";});CompletableFuture<String> 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<Void> 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<String> completableFuture1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1001);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("completableFuture1-当前线程名称:" + Thread.currentThread().getName());return "当前线程1执行结束";});CompletableFuture<String> completableFuture2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1001);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("completableFuture2-当前线程名称:" + Thread.currentThread().getName());return "当前线程2执行结束";});CompletableFuture<Object> 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<String> 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执行结束

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/64110.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Latex】使用技能站:(三)使用 Vscode 配置 LaTeX

使用 Vscode 配置 LaTeX 引言1 安装texlive2 安装vscode2.1 插件安装2.2 配置 3 安装SumatraPdf3.1 vscode配置3.2 配置反向搜索 引言 安装texlive 安装vscode 安装SumatraPdf 1 安装texlive 在线LaTeX编辑器&#xff1a;https://www.overleaf.com TeX Live下载&#xff1a;h…

使用 v-for 指令和数组来实现在 Uni-app 中动态增减表单项并渲染多个数据

在 data 中定义一个数组&#xff0c;用于存储表单项的数据&#xff1a; data() {return {formItems: []} } 在模板中使用 v-for 指令渲染表单项&#xff1a; <template><div><div v-for"(item, index) in formItems" :key"index"><…

【LeetCode】《LeetCode 101》第十二章:字符串

文章目录 12.1 字符串比较242 . 有效的字母异位词&#xff08;简单&#xff09;205. 同构字符串&#xff08;简单&#xff09;647. 回文子串&#xff08;中等&#xff09;696 . 计数二进制子串&#xff08;简单&#xff09; 12.2 字符串理解224. 基本计算器&#xff08;困难&am…

mysql之存储引擎

目录 存储引擎概念 MyISAM MyISAM特点 MyISAM 表的存储格式 MyISAM适用的生产场景 InnoDB InnoDB特点 选择存储引擎依据 MyISAM 和 INNODB区别 命令 查看系统支持的存储引擎 查看表使用的存储引擎 修改存储引擎 存储引擎概念 MySQL中的数据用各种不同的技术存…

通过python 获取当前局域网内存在的IP和MAC

通过python 获取当前局域网内存在的ip 通过ipconfig /all 命令获取局域网所在的网段 通过arp -d *命令清空当前所有的arp映射表 循环遍历当前网段所有可能的ip与其ping一遍建立arp映射表 for /L %i IN (1,1,254) DO ping -w 1 -n 1 192.168.3.%i 通过arp -a命令读取缓存的映射表…

Java的23种设计模式

Java的23种设计模式 一、创建型设计模式1.单例模式 singleton1.1.静态属性单例模式1.2 静态属性变种1.3 基础的懒汉模式1.4 线程安全的懒加载单例1.5 线程安全的懒加载 单例-改进1.6 双重检查锁1.7 静态内部类1.8 枚举单例1.9 注册表单例 2.工厂方法模式 factory3.抽象工厂模式…

通过chatgpt 学习React的useEffect

定义&#xff1a; useEffect 是 React 中的一个 Hook&#xff0c;它用于处理函数组件中的副作用操作。副作用操作可以包括数据获取、订阅事件、定时器等。 useEffect 接受两个参数&#xff1a;第一个参数是一个回调函数&#xff0c;用于执行副作用操作&#xff1b;第二个参数…

IE浏览器攻击:MS11-003_IE_CSS_IMPORT

目录 概述 利用过程 漏洞复现 概述 MS11-003_IE_CSS_IMPORT是指Microsoft Security Bulletin MS11-003中的一个安全漏洞&#xff0c;影响Internet Explorer&#xff08;IE&#xff09;浏览器。这个漏洞允许攻击者通过在CSS文件中使用import规则来加载外部CSS文件&#xff0…

SMU学习

SMU学习 1.参考资料 1.参考资料 TC3xx-SMU_EMS分析 英飞凌基础学习笔记&#xff08;SMU&#xff09;Safety Management Unit 为什么需要外部看门狗&#xff1f; ISO 26262 - Software Level of Functional Safety 简要概括下infeneon 芯片的SMU模块 ChatGPT 英飞凌&#xff0…

计算一个区间时间差值,时间保留剩下的差值

解决目的 begin end&#xff0c;去除集合类的其他区间差值List<rang> r1 new ArrayList(); 得到差值package com.jowoiot.wmzs.utils.date;import com.google.common.collect.Lists; import com.google.common.collect.Range; import org.apache.commons.lang.time.Dat…

51单片机项目(8)——基于51单片机的DS1302时钟系统

本次做的设计&#xff0c;是利用DS1302时钟芯片&#xff0c;做了一个时钟&#xff0c;并且将实时时间通过串口发送到上位机进行显示。系统运行如下&#xff1a;&#xff08;protues文件和相关keil代码会在文章最后给出&#xff01;&#xff01;&#xff01;&#xff09; DS1302…

[ES]二基础 |

一、索引库操作 1、mapping属性 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; 1)type&#xff1a;字段数据类型&#xff0c;常见的简单类型有&#xff1a; ①字符串&#xff1a;text(可分词的文本)、keyword&#xff08;精确值&#xff0c…

如何使用vue-smooth-dnd

Vue Smooth DnD是一个基于Vue的平滑易用的拖放库。它提供了简单易用的API和可自定义的样式。 要使用Vue Smooth DnD&#xff0c;可以按照以下步骤进行操作&#xff1a; 安装Vue Smooth DnD npm install vue-smooth-dnd --save 在组件中引入Vue Smooth DnD import VueSmoot…

【Leetcode】127.单词接龙(Hard)

一、题目 1、题目描述 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s 1 s_1 s1​

【LeetCode每日一题】——274.H指数

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 排序 二【题目难度】 中等 三【题目编号】 274.H指数 四【题目描述】 给你一个整数数组 ci…

如何使用RPA + ChatGPT自动化提高自己的工作效率

使用RPA&#xff08;Robotic Process Automation&#xff09;和ChatGPT可以结合来自动化提高自己的工作效率。下面是一些步骤&#xff1a; &#xff08;1&#xff09;确定自动化任务 首先&#xff0c;需要确定哪些任务或工作流程可以通过自动化来提高效率。这些任务应该是重复…

Qt无边框青绿色主题

收费产品&#xff0c;学生党、闹眼子党勿扰 收费金额&#xff1a;500元 1 概述 最近因项目需要&#xff0c;写了一个炫酷的青绿色、无边框界面&#xff0c;和3DSMax的界面有点类似。 2 截图 首先看看3DSMax的界面 不知道大家看出来没&#xff0c;这个ui其实很简单&#xff…

ELK安装、部署、调试 (七)kibana的安装与配置

1.介绍 Kibana 是一个基于浏览器的开源可视化工具&#xff0c;主要用于分析大量日志&#xff0c;以折线图、条形图、饼图、热图、区域图、坐标图、仪表、目标、时间等形式。预测或查看输入源的错误或其他重大事件趋势的变化。Kibana 与 Elasticsearch 和 Logstash 同步工作&am…

15年检测生涯转瞬即逝,复旦MBA助力邢国芒实现质量强国梦

日月光华&#xff0c;旦复旦兮&#xff01;复旦MBA如同一个巨大的磁场&#xff0c;吸引了诸多来自五湖四海、各行各业的职场精英。从初入职场的青涩懵懂到如今的独当一面专业干练&#xff0c;他们逐渐成长为职场的中坚力量&#xff0c;在各自领域内发光发热。作为新时代的青年&…

Positive Technologies:五分之四的网络攻击具有针对性

Positive Technologies 对 2023 年第二季度的相关网络威胁进行了分析。报告显示&#xff0c;自今年年初以来&#xff0c;有针对性的攻击数量增加了 10%&#xff0c;目前占 78%。专家们注意到利用漏洞的大规模攻击和大量用户个人数据的泄露。此外&#xff0c;在此期间&#xff0…