写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
示例五:异常处理
接着上一篇记录一下CompletableFuture的异常处理,异常处理通常使用exceptionally、whenComplete、handle相关方法,他们之间有一点区别,exceptionally相当于try/catch,whenComplete和handle相当于try/finally。
以下先演示下exceptionally的使用方式,exceptionally 就相当于 catch,出现异常,将会跳过 thenApply 的后续操作,直接捕获异常,进行一场处理,代码如下:
static void exceptionally() throws Exception{
CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> "执行:" + 10/0)
.thenApply(s -> {
System.out.println("执行了");
s += "a";
return s;
})
//.exceptionally(e -> "100")
.exceptionally(e -> {
System.out.println(e.getMessage());
return "100";
});
System.out.println(futureA.get());
}
执行结果如下:
可以看出如果出现异常会直接跳到exceptionally中处理异常,可以获取到异常信息并进行一些补偿操作,前面的操作直接跳过不再执行。
接下来看下whenComplete()对异常的处理,代码如下:
static void whenComplete() throws Exception{
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> 10/0)
.thenApply(s -> {
System.out.println("执行了");
return s + 1;
})
.whenComplete((r,e) -> {
if(r != null && e == null){
System.out.println("正常执行");
}
if(e != null){
System.out.println("执行异常:" + e.getMessage());
}
});
System.out.println(futureA.get());
}
执行结果如下:
可以看出,出现异常后,也没执行thenApply中的操作,而是直接跳到whenComplete方法中,但是控制台还报错了,上面说到,whenComplete相当于try/finally操作,没有catch异常肯定会报错,实际用的时候需要结合exceptionally使用,如下追加exceptionally处理:
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> 10/0)
.thenApply(s -> {
System.out.println("执行了");
return s + 1;
}).exceptionally(e -> {
System.out.println(e.getMessage());
return 100;
})
.whenCompleteAsync((r,e) -> {
if(r != null && e == null){
System.out.println("正常执行");
}
if(e != null){
System.out.println("执行异常:" + e.getMessage());
}
});
System.out.println(futureA.get());
执行结果如下:
handle跟whenComplete的区别是handle是有返回值的,使用handle的代码如下:
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> 10/0)
.thenApply(s -> {
System.out.println("执行了");
return s + 1;
}).exceptionally(e -> {
System.out.println(e.getMessage());
return 100;
})
.handle((r,e) -> {
if(r != null && e == null){
System.out.println("正常执行");
}
if(e != null){
System.out.println("执行异常:" + e.getMessage());
}
return 1;
});
System.out.println(futureA.get());
执行结果如下:
从结果上看,使用handle与使用whenComplete时,除了handle需要返回结果的不同外,最后打印的结果是也不同,使用handle最终futureA打印的结果是1,也就是说使用的是handle中返回的结果,从try/catch/finally运行的流程来说这种结果也是意料之中。