我有以下代码:
// 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
}
someFunc()
抛出 ServerException
。我不想在这里处理这个问题,而是将 someFunc()
的异常抛出给 myFunc()
的调用者。
最佳答案
您的代码表明您稍后在同一方法中使用异步操作的结果,因此无论如何您都必须处理 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
}
在调用 join
时,Supplier
的异步处理中抛出的所有异常都将被包装到 CompletionException
中,ServerException 除外
我们已经包裹在 CompletionException
中。
当我们重新抛出 CompletionException
的原因时,我们可能会遇到未经检查的异常,即 Error
或 RuntimeException
的子类,或者我们的自定义检查异常 ServerException
。上面的代码使用 multi-catch 处理所有这些,这将重新抛出它们。由于 getCause()
声明的返回类型是 Throwable
,编译器要求我们处理该类型,尽管我们已经处理了所有可能的类型。直接的解决方案是将这个实际上不可能的 throwable 包裹在 AssertionError
中。
或者,我们可以为自定义异常使用替代结果 future:
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
}
此解决方案将以包装形式重新抛出所有“意外”的 throwable,但仅以通过 exception
future 传递的原始形式抛出自定义 ServerException
。请注意,在查询 exception
future 之前,我们必须确保 a
已经完成(例如先调用 join()
),以避免竞争条件。
关于java - 从 CompletableFuture 抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44409962/