跳至主要內容

whenComplete、exceptionally

Jin大约 2 分钟

whenComplete、exceptionally

参考

官网open in new window

whenComplete

whenComplete 默认(不使用线程池)

    @Test
    void test01() {
        CompletableFuture.supplyAsync(() -> {
            System.out.println("线程名1    " + Thread.currentThread().getName());
            int i = 1 / 0;
            return null;
        }).whenComplete((k, e) -> {
            System.out.println("线程名2    " + Thread.currentThread().getName());
            System.out.println(k);
            System.out.println(e);
        }).whenComplete((k, e) -> {
            System.out.println("线程名3    " + Thread.currentThread().getName());
            System.out.println(k);
            System.out.println(e);
        });
    }

结果

  1. 线程名1 ForkJoinPool.commonPool-worker-9
  2. 线程名2 main(有异常 偶发ForkJoinPool.commonPool-worker-9)
  3. 线程名3 main(有异常 偶发ForkJoinPool.commonPool-worker-9)

whenComplete 使用自定义线程池

    @Test
    void test02() {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture.supplyAsync(() -> {
            System.out.println("线程名1    " + Thread.currentThread().getName());
//            int i = 1 / 0;
            return 1;
//            return null;
        }, executorService).whenComplete((k, e) -> {
            System.out.println("线程名2    " + Thread.currentThread().getName());
        }).whenComplete((k, e) -> {
            System.out.println("线程名3    " + Thread.currentThread().getName());
        });
    }

结果

  • 模拟异常场景
    1. 线程名1 pool-1-thread-1
    2. 线程名2 pool-1-thread-1(偶发为main)
    3. 线程名3 main
  • 模拟supplyAsync返回null 和非 null
    1. 线程名1 pool-1-thread-1
    2. 线程名2 main
    3. 线程名3 main

whenCompleteAsync 默认(不使用自定义线程池)

    @Test
    void test03() {
        CompletableFuture.supplyAsync(() -> {
            System.out.println("线程名1    " + Thread.currentThread().getName());
//            int i = 1 / 0;
//            return 1;
            return null;
        }).whenCompleteAsync((k, e) -> {
            System.out.println("线程名2    " + Thread.currentThread().getName());
        }).whenCompleteAsync((k, e) -> {
            System.out.println("线程名3    " + Thread.currentThread().getName());
        });
    }
  • supplyAsync返回不为null 或 非 null
    1. 线程名1 ForkJoinPool.commonPool-worker-9
    2. 线程名2 ForkJoinPool.commonPool-worker-9
    3. 线程名3 ForkJoinPool.commonPool-worker-9
  • 有异常返回null 或 非 null
    1. 线程名1 ForkJoinPool.commonPool-worker-9
    2. 线程名2 ForkJoinPool.commonPool-worker-9
    3. 线程名3 ForkJoinPool.commonPool-worker-9

whenCompleteAsync 使用线程池

    @Test
    void test04() {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        CompletableFuture.supplyAsync(() -> {
            System.out.println("线程名1    " + Thread.currentThread().getName());
            int i = 1 / 0;
//            return null;
            return 1;
        }, executorService).whenCompleteAsync((k, e) -> {
            System.out.println("线程名2    " + Thread.currentThread().getName());
        }, executorService).whenCompleteAsync((k, e) -> {
            System.out.println("线程名3    " + Thread.currentThread().getName());
        }, executorService);
    }

结果:

  • 各种场景测试结果
    1. 线程名1 pool-1-thread-1
    2. 线程名2 pool-1-thread-2
    3. 线程名3 pool-1-thread-3

总结

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

  1. 正常完成:whenComplete返回结果和上级任务一致,异常为null;
  2. 出现异常:whenComplete返回结果为null,异常为上级任务的异常;
  3. 即调用get()时,正常完成时就获取到结果,出现异常时就会抛出异常,需要你处理该异常。

whenComplete可以处理正常和异常的计算结果,exceptionally处理异常情况。BiConsumer<? super T,? super Throwable>可以定义处理业务

whenCompletewhenCompleteAsync 的区别: whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。 whenCompleteAsync:是

执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。

贡献者: Jin