Java异步执行器CompletableFuture使用详解

一、简介

Future实际采用FutureTask实现,该对象相当于是消费者和生产者的桥梁,消费者通过FutureTask存储任务的处理结果,更新任务的状态:未开始、正在处理、已完成等。而生产者拿到的FutureTask被转型为Future接口,可以阻塞式获取任务的处理结果,非阻塞式获取任务处理状态。

CompletableFutureJDK8提供的Future增强类。CompletableFuture异步任务执行线程池,默认是把异步任务都放在ForkJoinPool中执行。

在这种方式中,主线程不会被阻塞,不需要一直等到子线程完成。主线程可以并行的执行其他任务。

二、创建异步任务

CompletableFuture提供了四个静态方法来创建一个异步操作。

public static CompletableFuture<Void> runAsync(Runnable runnable);
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);

没有指定Executor的方法会使用ForkJoinPool.commonPool()作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同。

  • runAsync方法不支持返回值。
  • supplyAsync可以支持返回值。

2.1 runAsync

runAsync表示创建无返回值的异步任务,相当于ExecutorService submit(Runnable task)方法。

示例

//无返回值
public static void runAsync() throws Exception {
    CompletableFuture<Void> f = CompletableFuture.runAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        System.out.println("run end ...");
    });
    f.get();
}

2.2 supplyAsync

supplyAsync表示创建带返回值的异步任务的,相当于ExecutorService submit(Callable<T> task)方法。

示例

//有返回值
public static void supplyAsync() throws Exception {         
    CompletableFuture<Long> f = CompletableFuture.supplyAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        System.out.println("run end ...");
        return System.currentTimeMillis();
    });
    long time = f.get();
    System.out.println("time = " + time);
}

三、结果处理

3.1 whenComplete

whenComplete是当某个任务执行完成后执行的回调方法,会将执行结果或者执行期间抛出的异常传递给回调方法,如果是正常执行则异常为null,回调方法对应的CompletableFutureresult和该任务一致,如果该任务正常执行,则get方法返回执行结果,如果是执行异常,则get方法抛出异常。

public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action);

public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);
public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action,
                                              Executor executor);

可以看到Action的类型是BiConsumer<? super T, ? super Throwable>它可以处理正常的计算结果,或者异常情况。

whenCompletewhenCompleteAsync的区别:

  • whenComplete:是执行当前任务的线程执行继续执行whenComplete的任务。
  • whenCompleteAsync:是执行把whenCompleteAsync这个任务继续提交给线程池来进行执行。

示例

public static void whenComplete() throws Exception {
    CompletableFuture<Void> f = CompletableFuture.runAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        if (new Random().nextInt() % 2 >= 0) {
            int i = 12 / 0;
        }
        System.out.println("run end ...");
    });
    f.whenComplete(new BiConsumer<Void, Throwable>() {
        @Override
        public void accept(Void t, Throwable action) {
            System.out.println("执行完成!");
        }
    });
    TimeUnit.SECONDS.sleep(2);
}

3.2 exceptionally

exceptionally方法指定某个任务执行异常时执行的回调方法,会将抛出异常作为参数传递到回调方法中,如果该任务正常执行则会exceptionally方法返回的CompletionStageresult就是该任务正常执行的结果。

public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn);

示例

public static void exceptionally() throws Exception {
    CompletableFuture<Void> f = CompletableFuture.runAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        if (new Random().nextInt() % 2 >= 0) {
            int i = 12 / 0;
        }
        System.out.println("run end ...");
    });
    f.whenComplete(new BiConsumer<Void, Throwable>() {
        @Override
        public void accept(Void t, Throwable action) {
            System.out.println("执行完成!");
        }
    });
    f.exceptionally(new Function<Throwable, Void>() {
        @Override
        public Void apply(Throwable t) {
            System.out.println("执行失败!" + t.getMessage());
            return null;
        }
    });
    TimeUnit.SECONDS.sleep(2);
}

3.3 handle

handle是执行任务完成时对结果的处理。

handle方法和thenApply方法处理方式基本一样。不同的是handle是在任务完成后再执行,还可以处理异常的任务。thenApply只可以执行正常的任务,任务出现异常则不执行thenApply方法。

public <U> CompletionStage<U> handle(BiFunction<? super T, Throwable, ? extends U> fn);

public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn);
public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,
                                          Executor executor);

示例

public static void handle() throws Exception {
    CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int i= 10/0;
            return new Random().nextInt(10);
        }
    }).handle(new BiFunction<Integer, Throwable, Integer>() {
        @Override
        public Integer apply(Integer param, Throwable throwable) {
            int result = -1;
            if (throwable == null) {
                result = param * 2;
            } else {
                System.out.println(throwable.getMessage());
            }
            return result;
        }
     });
    System.out.println(f.get());
}

从示例中可以看出,在handle中可以根据任务是否有异常来进行做相应的后续处理操作。而thenApply方法,如果上个任务出现错误,则不会执行thenApply方法。

四、串行执行

4.1 thenApply

当一个线程依赖另一个线程时,可以使用thenApply方法来把这两个线程串行化。

public <U> CompletableFuture<U> thenApply(Function<? super T, ? extends U> fn);

public <U> CompletableFuture<U> thenApplyAsync(Function<? super T, ? extends U> fn);
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T, ? extends U> fn,
                                               Executor executor);

参数Function<? super T,? extends U>说明

  • T:上一个任务返回结果的类型
  • U:当前任务的返回值类型

示例

private static void thenApply() throws Exception {
    CompletableFuture<Long> f = CompletableFuture.supplyAsync(new Supplier<Long>() {
        @Override
        public Long get() {
            long result = new Random().nextInt(100);
            System.out.println("result1 = " + result);
            return result;
        }
    }).thenApply(new Function<Long, Long>() {
        @Override
        public Long apply(Long t) {
            long result = t * 5;
            System.out.println("result2 = " + result);
            return result;
        }
    });
    long result = f.get();
    System.out.println(result);
}

第二个任务依赖第一个任务的结果。

4.2 thenAccept

接收任务的处理结果,并消费处理,无返回结果。

public CompletionStage<Void> thenAccept(Consumer<? super T> action);

public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);
public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor);

示例

public static void thenAccept() throws Exception{
    CompletableFuture<Void> f = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            return new Random().nextInt(10);
        }
    }).thenAccept(integer -> {
        System.out.println(integer);
    });
    f.get();
}

从示例代码中可以看出,该方法只是消费执行完成的任务,并可以根据上面的任务返回的结果进行处理。并没有后续的输出操作。

4.3 thenRun

thenAccept方法不一样的是,不关心任务的处理结果。只要上面的任务执行完成,就开始执行thenAccept

public CompletionStage<Void> thenRun(Runnable action);

public CompletionStage<Void> thenRunAsync(Runnable action);
public CompletionStage<Void> thenRunAsync(Runnable action, Executor executor);

示例

public static void thenRun() throws Exception {
    CompletableFuture<Void> f = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            return new Random().nextInt(10);
        }
    }).thenRun(() -> {
        System.out.println("thenRun ...");
    });
    f.get();
}

该方法同thenAccept方法类似。不同的是上个任务处理完成后,并不会把计算的结果传给thenRun方法。只是处理玩任务后,执行thenAccept的后续操作。

五、组合运算

5.1 thenCompose

thenCompose方法允许你对两个CompletionStage进行流水线操作,第一个操作完成时,将其结果作为参数传递给第二个操作。

public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);

public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn,
                                                 Executor executor);

示例

private static void thenCompose() throws Exception {
    CompletableFuture<Integer> f = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            System.out.println("t1 = " + t);
            return t;
        }
    }).thenCompose(new Function<Integer, CompletionStage<Integer>>() {
        @Override
        public CompletionStage<Integer> apply(Integer param) {
            return CompletableFuture.supplyAsync(new Supplier<Integer>() {
                @Override
                public Integer get() {
                    int t = param * 2;
                    System.out.println("t2 = " + t);
                    return t;
                }
            });
        }
    });
    System.out.println("thenCompose result : " + f.get());
}

5.2 thenCombine

thenCombine会把两个CompletionStage的任务都执行完成后,把两个任务的结果一块交给thenCombine来处理。

public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other,
                                            BiFunction<? super T, ? super U,? extends V> fn);

public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,
                                                 BiFunction<? super T, ? super U, ? extends V> fn);
public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,
                                                 BiFunction<? super T, ? super U, ? extends V> fn,
                                                 Executor executor);

示例

private static void thenCombine() throws Exception {
    CompletableFuture<String> f1 = CompletableFuture.supplyAsync(new Supplier<String>() {
        @Override
        public String get() {
            return "hello";
        }
    });
    CompletableFuture<String> f2 = CompletableFuture.supplyAsync(new Supplier<String>() {
        @Override
        public String get() {
            return "hello";
        }
    });
    CompletableFuture<String> result = f1.thenCombine(f2, new BiFunction<String, String, String>() {
        @Override
        public String apply(String t, String u) {
            return t + " " + u;
        }
    });
    System.out.println(result.get());
}

5.3 thenAcceptBoth

当两个CompletionStage都执行完成后,把结果一块交给thenAcceptBoth来进行消耗。

public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,
                                                BiConsumer<? super T, ? super U> action);

public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
                                                     BiConsumer<? super T, ? super U> action);
public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
                                                     BiConsumer<? super T, ? super U> action,
                                                     Executor executor);

示例

private static void thenAcceptBoth() throws Exception {
    CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f1 = " + t);
            return t;
        }
    });
    CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f2 = " + t);
            return t;
        }
    });
    f1.thenAcceptBoth(f2, new BiConsumer<Integer, Integer>() {
        @Override
        public void accept(Integer t, Integer u) {
            System.out.println("f1 = " + t + ";f2 = " + u + ";");
        }
    });
}

5.4 runAfterBoth

两个CompletionStage,都完成了计算才会执行下一步的操作(Runnable)。

public CompletionStage<Void> runAfterBoth(CompletionStage<?> other, Runnable action);

public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action);
public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other, Runnable action,
                                               Executor executor);

示例

private static void runAfterBoth() throws Exception {
    CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f1 = " + t);
            return t;
        }
    });
    CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f2 = " + t);
            return t;
        }
    });
    f1.runAfterBoth(f2, new Runnable() {
        @Override
        public void run() {
            System.out.println("上面两个任务都执行完成了。");
        }
    });
}

六、Either

acceptEitherrunAfterEitherapplyToEither这三个方法只取组合线程中执行最快的一个结果。

6.1 acceptEither

两个CompletionStage,谁执行返回的结果快,就用那个CompletionStage的结果进行下一步的消耗操作。

public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,
                                          Consumer<? super T> action);

public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,
                                               Consumer<? super T> action);
public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,
                                               Consumer<? super T> action,
                                               Executor executor);

示例

private static void acceptEither() throws Exception {
    CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f1 = " + t);
            return t;
        }
    });
    CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f2 = " + t);
            return t;
        }
    });
    f1.acceptEither(f2, new Consumer<Integer>() {
        @Override
        public void accept(Integer t) {
            System.out.println(t);
        }
    });
}

6.2 applyToEither

两个CompletionStage,谁执行返回的结果快,就用那个CompletionStage的结果进行下一步的转化操作。

public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,
                                            Function<? super T, U> fn);

public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,
                                                 Function<? super T, U> fn);
public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,
                                                 Function<? super T, U> fn,
                                                 Executor executor);

示例

private static void applyToEither() throws Exception {
    CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f1 = " + t);
            return t;
        }
    });
    CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f2 = " + t);
            return t;
        }
    });
    CompletableFuture<Integer> result = f1.applyToEither(f2, new Function<Integer, Integer>() {
        @Override
        public Integer apply(Integer t) {
            System.out.println(t);
            return t * 2;
        }
    });
    System.out.println(result.get());
}

6.3 runAfterEither

两个CompletionStage,任何一个完成了都会执行下一步的操作(Runnable)。

public CompletionStage<Void> runAfterEither(CompletionStage<?> other, Runnable action);

public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action);
public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other, Runnable action,
                                                 Executor executor);

示例

private static void runAfterEither() throws Exception {
    CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f1 = " + t);
            return t;
        }
    });
    CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f2 = " + t);
            return t;
        }
    });
    f1.runAfterEither(f2, new Runnable() {
        @Override
        public void run() {
            System.out.println("上面有一个已经完成了。");
        }
    });
}

七、辅助方法

allOfanyOf可以组合任意多个CompletableFuture

allOfanyOf的区别:

  • allof等待所有任务执行完成才执行。
  • anyOf是只要有一个任务执行完成。

7.1 allOf

allOf返回的CompletableFuture是多个任务都执行完成后才会执行,只要有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null

返回值是CompletableFuture类型,这是因为每个传入的CompletableFuture的返回值都可能不同,所以组合的结果是无法用某种类型来表示的,索性返回Void类型。

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs);

示例

private static void allOf() throws Exception {
    // 创建异步执行任务
    CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f1 = " + t);
            return t;
        }
    });
    CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f2 = " + t);
            return t;
        }
    });

    // allOf等待所有任务执行完成才执行f3,如果有一个任务异常终止,则f3.get时会抛出异常,都是正常执行,f3.get返回null
    CompletableFuture f3 = CompletableFuture.allOf(f1, f2).whenComplete((a, b) -> {
        if (b != null) {
            System.out.println("error stack trace ->");
            b.printStackTrace();
        } else {
            System.out.println("run succ,result ->" + a);
        }
    });
}

示例2

并行下载100个网页,待下载完成之后,统计在100个网页中,含有某个单词的网页个数。

// url列表集合
List<String> webPageLinks = Arrays.asList("...");

// 并行下载
List<CompletableFuture> pageFutures = webPageLinks.stream()
        .map(webPageLink -> downLoadWebPage(webPageLink))
        .collect(Collectors.toList());
		
// 通过allOf,等待所有网页下载完,收集返回结果
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
        pageFutures.toArray(new CompletableFuture[pageFutures.size()])
);

示例3

多个线程异步调用远程接口,最后汇总结果统一返回。

//线程池定义
private static final ExecutorService executorService = new ThreadPoolExecutor(1, 5, 60,
        TimeUnit.MINUTES, new ArrayBlockingQueue<>(512));

//具体处理逻辑
@Override
public List<Order> getDataListByBatch(OrderQueryDo dataQuery, int totalSize) {
    //防止并发操作情况下出现 并发修改异常,单线程不存在这个问题,CopyOnWriteArrayList底层使用Lock锁,性能可以被保证
    List<Order> dataList = new CopyOnWriteArrayList<>();
    //获取总页数
    int totalPage = getTotalPage(totalSize, dataQuery.getRows());
    //获取页数
    List<Integer> pageNumbers = getPageNumbers(totalPage);
    log.info("getDataListByBatch() -> request: {}, totalSize: [{}], totalPage: [{}]",
            JSON.toJSONString(dataQuery), totalSize, totalPage);
    //计时器
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    //异步回调
    CompletableFuture[] completableFutures = pageNumbers.stream()
            .map(pageNumber -> CompletableFuture.supplyAsync(() -> {
                //执行分页查询
                dataQuery.setPage(pageNumber);
                Result<PageInfo<Order>> listPage = selectPage(dataQuery);
                //返回数据
                return Objects.nonNull(listPage.getData())
                        ? listPage.getData().getRecords()
                        : new ArrayList<Order>();
            }, executorService).whenComplete((bodyList, throwable) -> { //处理结果
                if (!ObjectUtils.isEmpty(bodyList)) {
                    //将数据添加到list中
                    dataList.addAll(bodyList);
                }
            })).toArray(CompletableFuture[]::new);
    //所有任务执行完才放行
    CompletableFuture.allOf(completableFutures).join();
    stopWatch.stop();
    log.info("getDataListByBatch() -> stopWatch: {}ms", stopWatch.getTotalTimeMillis());
    return dataList;
}

/**
 * 处理总页数
 *
 * @param totalSize
 * @return
 */
private int getTotalPage(int totalSize, int row) {
    return (totalSize % row == 0)
            ? (totalSize / row)
            : (totalSize / row + 1);
}

/**
 * 获取页数
 *
 * @param totalPage
 * @return
 */
private List<Integer> getPageNumbers(int totalPage) {
    int pageNumber = 1;
    List<Integer> pageNumbers = Lists.newArrayList();
    while (pageNumber <= totalPage) {
        pageNumbers.add(pageNumber++);
    }
    return pageNumbers;
}

7.2 anyOf

anyOf方法的参数是多个给定的CompletableFuture,当其中的任何一个完成时,方法返回这个CompletableFuture

但由于每个CompletableFuture的返回值类型都可能不同,任意一个,意味着无法判断是什么类型,所以anyOf的返回值是CompletableFuture类型。

public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs);

示例

private static void anyOf() throws Exception {
    // 创建异步执行任务
    CompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f1 = " + t);
            return t;
        }
    });
    CompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            int t = new Random().nextInt(3);
            try {
                TimeUnit.SECONDS.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("f2 = " + t);
            return t;
        }
    });

    // anyOf是只有一个任务执行完成,无论是正常执行或者执行异常,都会执行f3,f3.get的结果就是已执行完成的任务的执行结果
    CompletableFuture<Object> f3 = CompletableFuture.anyOf(f1, f2).whenComplete((a, b) -> {
        if (b != null) {
            System.out.println("error stack trace ->");
            b.printStackTrace();
        } else {
            System.out.println("run succ, result ->" + a);
        }
    });
}

在该例子中,因为f1f2的返回值都是CompletableFuture,所以anyOf的返回的Object一定也是Integer类型。

参考文章

posted @ 2022-04-25 16:35  夏尔_717  阅读(608)  评论(0编辑  收藏  举报