whenComplete、exceptionally
大约 2 分钟
whenComplete、exceptionally
参考
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 ForkJoinPool.commonPool-worker-9
- 线程名2 main(有异常 偶发ForkJoinPool.commonPool-worker-9)
- 线程名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 pool-1-thread-1
- 线程名2 pool-1-thread-1(偶发为main)
- 线程名3 main
- 模拟
supplyAsync
返回null
和非null
- 线程名1 pool-1-thread-1
- 线程名2 main
- 线程名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 ForkJoinPool.commonPool-worker-9
- 线程名2 ForkJoinPool.commonPool-worker-9
- 线程名3 ForkJoinPool.commonPool-worker-9
- 有异常返回
null
或 非null
- 线程名1 ForkJoinPool.commonPool-worker-9
- 线程名2 ForkJoinPool.commonPool-worker-9
- 线程名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 pool-1-thread-1
- 线程名2 pool-1-thread-2
- 线程名3 pool-1-thread-3
总结
当CompletableFuture
的任务不论是正常完成,还是出现异常它都会调用whenComplete
这回调函数。
- 正常完成:whenComplete返回结果和上级任务一致,异常为null;
- 出现异常:whenComplete返回结果为null,异常为上级任务的异常;
- 即调用get()时,正常完成时就获取到结果,出现异常时就会抛出异常,需要你处理该异常。
whenComplete
可以处理正常和异常的计算结果,exceptionally
处理异常情况。BiConsumer<? super T,? super Throwable>可以定义处理业务
whenComplete
和 whenCompleteAsync
的区别: whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。 whenCompleteAsync:是
执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行。