Создайте исключение в / после завершаемого будущего - PullRequest
1 голос
/ 01 ноября 2019

У меня есть список завершаемых фьючерсов:завершить весь асинхронный процесс при обнаружении генерируемого исключения.

1 Ответ

4 голосов
/ 01 ноября 2019

Нет необходимости в такой конструкции, как

try { 
    return helper(c);
}catch(Throwable th) {
   throw th;
}

, поскольку поведение по отлову и повторному выбрасыванию исключения не отличается от того, чтобы не перехватить исключение в первую очередь. Аналогично, цепочка .exceptionally(ex -> { throw ex; } была бы бессмысленной, если бы она была законной. (Это не так, поскольку Throwable является проверенным исключением.

Если помощник не выбрасывает проверенные исключения, вы можете просто использовать CompletableFuture.supplyAsync(() -> helper(c)). В противном случае вы должны заключить проверенные исключения в непроверенные исключения;самый естественный выбор здесь будет CompletionException.

Это будет выглядеть следующим образом:

List<CompletableFuture<MyObject>> futures = class_list.stream()
    .map(c -> CompletableFuture.supplyAsync(() ->
        try { 
            return helper(c);
        } catch(Throwable th) {
            throw new CompletionException(th);
        }
    ))
    .collect(Collectors.toList());

Ваша вторая операция тихая небрежно. Имя класса CompletionException, а не CompletionexceptionДалее, выброс существующего исключения, хранящегося в переменной ex, выполняется с помощью throw ex;, а не throw new ex;. Но, как уже было сказано, когда вы хотите, чтобы исключение было (пере) выброшено, просто не перехватывайте егопервое место.

Проблема в том, что get выбрасывает проверенный ExecutionException, а не непроверенный CompletionException. Для последнего вы должны использовать join. Таким образом, вы можете достичь желаемого результата. -бросок через

 // will throw when any future completed exceptionally
futures.forEach(CompletableFuture::join);
...