写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
示例五:异常处理
接着上一篇记录一下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运行的流程来说这种结果也是意料之中。












