一、whenComplete的作用

当CompletableFuture的任务不论是正常完成还是出现异常它都会调用whenComplete这回调函数。

  • 正常完成:whenComplete返回结果和上级任务一致,异常为null;
  • 出现异常:whenComplete返回结果为null,异常为上级任务的异常;

即调用get()时,正常完成时就获取到结果,出现异常时就会抛出异常,需要你处理该异常。

二、测试案例

1. 只用whenComplete

public class Thread02_WhenComplete {

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {

            if (Math.random() < 0.5) {
                throw new RuntimeException("出错了");
            }
            System.out.println("正常结束");
            return 0.11;

        }).whenComplete(new BiConsumer<Double, Throwable>() {
            @Override
            public void accept(Double aDouble, Throwable throwable) {

                if (aDouble == null) {
                    System.out.println("whenComplete aDouble is null");
                } else {
                    System.out.println("whenComplete aDouble is " + aDouble);
                }

                if (throwable == null) {
                    System.out.println("whenComplete throwable is null");
                } else {
                    System.out.println("whenComplete throwable is " + throwable.getMessage());
                }
            }
        });

        System.out.println("最终返回的结果 = " + future.get());
    }
}

正常完成,没有异常时:

正常结束
whenComplete aDouble is 0.11
whenComplete throwable is null
最终返回的结果 = 0.11

出现异常时:
get()会抛出异常

whenComplete aDouble is null
whenComplete throwable is java.lang.RuntimeException: 出错了
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.RuntimeException: 出错了
	at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
	at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
	at cc.pigg.study.java.thread.Thread02_WhenComplete.main(Thread02_WhenComplete.java:40)

2. whenComplete + exceptionally

在上一篇博客介绍了exceptionally,它可以捕获异常,并给出异常时默认返回值。

public class Thread03_WhenComplete_Exceptionally {

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        CompletableFuture<Double> future = CompletableFuture.supplyAsync(() -> {
        
            if (Math.random() < 0.5) {
                throw new RuntimeException("出错了");
            }
            System.out.println("正常结束");
            return 0.11;

        }).whenComplete(new BiConsumer<Double, Throwable>() {
            @Override
            public void accept(Double aDouble, Throwable throwable) {

                if (aDouble == null){
                    System.out.println("whenComplete aDouble is null");
                } else {
                    System.out.println("whenComplete aDouble is " + aDouble);
                }

                if (throwable == null){
                    System.out.println("whenComplete throwable is null");
                } else {
                    System.out.println("whenComplete throwable is " + throwable.getMessage());
                }
            }
        }).exceptionally(new Function<Throwable, Double>() {
            @Override
            public Double apply(Throwable throwable) {
                System.out.println("exceptionally中异常:" + throwable.getMessage());
                return 0.0;
            }
        });

        System.out.println("最终返回的结果 = " + future.get());
    }
}

当出现异常时,exceptionally中会捕获该异常,给出默认返回值0.0。
在用get()时,返回的就是exceptionally中指定的返回值0.0。

whenComplete aDouble is null
whenComplete throwable is java.lang.RuntimeException: 出错了
exceptionally中异常:java.lang.RuntimeException: 出错了
最终返回的结果 = 0.0
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐