ayu*_*hgp 25 java exception-handling exception java-8 completable-future
我有以下代码:
// How to throw the ServerException?
public void myFunc() throws ServerException{
// Some code
CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
try {
return someObj.someFunc();
} catch(ServerException ex) {
// throw ex; gives an error here.
}
}));
// Some code
}
Run Code Online (Sandbox Code Playgroud)
someFunc()抛出一个ServerException.我不想在这里处理这个问题,而是将异常抛给someFunc()调用者myFunc().
Hol*_*ger 43
您的代码建议您稍后在同一方法中使用异步操作的结果,因此您CompletionException无论如何都必须处理,因此处理它的一种方法是
public void myFunc() throws ServerException {
// Some code
CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
try { return someObj.someFunc(); }
catch(ServerException ex) { throw new CompletionException(ex); }
});
// Some code running in parallel to someFunc()
A resultOfA;
try {
resultOfA = a.join();
}
catch(CompletionException ex) {
try {
throw ex.getCause();
}
catch(Error|RuntimeException|ServerException possible) {
throw possible;
}
catch(Throwable impossible) {
throw new AssertionError(impossible);
}
}
// some code using resultOfA
}
Run Code Online (Sandbox Code Playgroud)
在异步处理中抛出的所有异常Supplier将CompletionException在调用时被包装到一个join,除了ServerException我们已经包装在一个CompletionException.
当我们重新抛出原因时CompletionException,我们可能会遇到未经检查的异常,即Erroror的子类RuntimeException,或者我们的自定义检查异常ServerException.上面的代码使用multi-catch处理所有这些代码,这将重新抛出它们.由于声明的返回类型getCause()是Throwable,编译器要求我们处理该类型,尽管我们已经处理了所有可能的类型.直截了当的解决办法就是扔掉这个实际上不可能的扔掉的东西AssertionError.
或者,我们可以为我们的自定义异常使用替代结果:
public void myFunc() throws ServerException {
// Some code
CompletableFuture<ServerException> exception = new CompletableFuture<>();
CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
try { return someObj.someFunc(); }
catch(ServerException ex) {
exception.complete(ex);
throw new CompletionException(ex);
}
});
// Some code running in parallel to someFunc()
A resultOfA;
try {
resultOfA = a.join();
}
catch(CompletionException ex) {
if(exception.isDone()) throw exception.join();
throw ex;
}
// some code using resultOfA
}
Run Code Online (Sandbox Code Playgroud)
此解决方案将以包装形式重新抛出所有"意外"抛出的抛出物,但只能将自定义ServerException以其原始形式投放到exception未来.请注意,在我们查询未来之前,我们必须确保a已完成(如join()先调用)exception,以避免竞争条件.
mel*_*ngs 23
对于那些寻求其他通过completableFuture处理异常的方法的人
以下是处理解析错误到整数的示例的几种方法:
1. using handle方法 -使您可以提供异常的默认值
CompletableFuture correctHandler = CompletableFuture.supplyAsync(() -> "A")
.thenApply(Integer::parseInt)
.handle((result, ex) -> {
if (null != ex) {
ex.printStackTrace();
return 0;
} else {
System.out.println("HANDLING " + result);
return result;
}
})
.thenAcceptAsync(s -> {
System.out.println("CORRECT: " + s);
});
Run Code Online (Sandbox Code Playgroud)
2.使用exceptionally方法 -相似handle但较不冗长
CompletableFuture parser = CompletableFuture.supplyAsync(() -> "1")
.thenApply(Integer::parseInt)
.exceptionally(t -> {
t.printStackTrace();
return 0;
}).thenAcceptAsync(s -> System.out.println("CORRECT value: " + s));
Run Code Online (Sandbox Code Playgroud)
3.使用whenComplete方法 -使用此方法将停止该方法的执行,而不会执行下一个thenAcceptAsync
CompletableFuture correctHandler2 = CompletableFuture.supplyAsync(() -> "A")
.thenApply(Integer::parseInt)
.whenComplete((result, ex) -> {
if (null != ex) {
ex.printStackTrace();
}
})
.thenAcceptAsync(s -> {
System.out.println("When Complete: " + s);
});
Run Code Online (Sandbox Code Playgroud)
4.通过传播异常 completeExceptionally
public static CompletableFuture<Integer> converter(String convertMe) {
CompletableFuture<Integer> future = new CompletableFuture<>();
try {
future.complete(Integer.parseInt(convertMe));
} catch (Exception ex) {
future.completeExceptionally(ex);
}
return future;
}
Run Code Online (Sandbox Code Playgroud)