Twój kod sugeruje, że używasz wyniku operacja asynchroniczna później w ten sam sposób, więc będziesz mieć do czynienia z CompletionException
tak, więc jednym ze sposobów radzenia sobie z nim, jest
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
}
Wszystkie wyjątki rzucane wewnątrz asynchronicznego przetwarzania Supplier
dostanie, zapakowane w CompletionException
podczas dzwonienia pod numer join
, z wyjątkiem ServerException
, który już został zawinięty w CompletionException
.
Kiedy ponownie rzucać przyczynę CompletionException
możemy zmierzyć niezaznaczone wyjątki, tj podklasy Error
lub RuntimeException
lub naszym zwyczajem sprawdzone wyjątku ServerException
. Powyższy kod obsługuje wszystkie z nich z wieloma połowami, które będą je ponownie rzucać. Ponieważ zadeklarowany typ zwrotu: getCause()
to Throwable
, kompilator wymaga od nas obsługi tego typu, mimo że mamy już do czynienia z wszystkimi możliwymi typami. Prostym rozwiązaniem jest rzucenie tego, co jest niemożliwe, z zapakowanym w AssertionError
.
Alternatywnie, możemy skorzystać z alternatywnej przyszłości wynik dla naszego niestandardowego wyjątek:
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
}
To rozwiązanie będzie ponownie rzucić wszystko „nieoczekiwane” throwables w ich zawinięte postaci, ale tylko rzut zwyczaj ServerException
w oryginale Formularz przekazany za pośrednictwem przyszłości exception
. Pamiętaj, że musimy upewnić się, że została zakończona a
(na przykład wywołanie join()
), zanim wyślemy zapytanie o przyszłość w postaci exception
, aby uniknąć warunków wyścigu.
to jest bardzo miłe ... – Eugene
bardzo szczegółowa odpowiedź. –