JDK8 CompletableFuture.supplyAsync как бороться с interruptedException
CompletableFuture.supplyAsync(
() -> {
transporter.write(req);
//here take the value from a blocking queue,will throw a interruptedException
return responseQueue.take();
}, executorService);
Общим методом борьбы с interruptedException является либо прерывание снова, либо прямой throw interruptedException, но оба они не могут работать. У кого-нибудь есть идея?
Ответы
Ответ 1
Я изменяю код следующим образом.
CompletableFuture<Rep> result = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
transporter.write(req);
try {
Rep rep = responseQueue.take();
result.complete(rep);
} catch (InterruptedException e) {
result.completeExceptionally(e);
Thread.currentThread().interrupt();
} catch (Exception e) {
result.completeExceptionally(e);
}
}, executorService);
return result;
Ответ 2
Поскольку функции лямбда не поддерживают исключение броска, я думаю, что разработчикам Java понадобится новая парадигма. Одна вещь, которая приходит на ум, такова:
public class ResultWrapper<R, E extends Exception> {
E exception;
R result;
}
Лямбда-функции могут возвращать экземпляры этой оболочки. (Изменить: ваш случай)
CompletableFuture<ResultWrapper<String, InterruptedException>> aFuture = ...;
...
aFuture.supplyAsync(
() -> {
try {
transporter.write(req);
} catch(InterruptedException e) {
ResultWrapper<String, InterruptedException> r = new ResultWrapper<>();
r.exception = e;
r.result = null;
return r;
}
...
}, executorService);
Ответ 3
Я столкнулся с тем же вопросом, но, прочитав больше комментариев отсюда и справочника, я думаю, вы можете сделать одно из этих двух:
1 (что я делаю):
CompletableFuture.runAsync(() -> {
transporter.write(req);
try {
Rep rep = responseQueue.take();
result.complete(rep);
} catch (Exception e) {
throw new CompletionException(e);
}
}, executorService);
return result;
или 2:
CompletableFuture<Rep> result = new CompletableFuture<>();
new Thread(()-> {
transporter.write(req);
try {
Rep rep = responseQueue.take();
result.complete(rep);
} catch (Exception e) {
retsult.completeExceptionally(e);
}
}).start();
Я знаю, что второй не использует executorService
, но я чувствую, что вся цель использования CompletableFuture - использование API CompletionStage в функциональном стиле.
Ответ 4
@antak упомянул об этом в комментариях, но я думаю, что правильный ответ здесь:
Для CompletableFuture.supplyAsync()
оберните его в java.util.concurrent.CompletionException
и перебросьте его.
Таким образом, пример кода будет выглядеть примерно так:
CompletableFuture.supplyAsync(
() -> {
transporter.write(req);
try {
//here take the value from a blocking queue,will throw a interruptedException
return responseQueue.take();
}
catch (InterruptedException e) {
throw new CompletionException(e);
}
}, executorService);