Гуава: Throwables.propagate и InterruptedException

как лучше всего обрабатывать InterruptedException при использовании Throwables.propagate(e) в Guava?

Мне нравится использовать throw Throwables.propagate(e), особенно в методах, которые не вызывают проверенных исключений и где обработка исключений является обязанностью вызывающей стороны. Но это не делает то, что я ожидаю от InterruptedException.

Я не хочу потерять тот факт, что поток был прерван, поэтому я заканчиваю тем, что пишу что-то вроде:

public void run() {
    Callable c = ...;
    try {
        c.call();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw Throwables.propagate(e);
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}

Есть ли способ сделать это в Гуаве? Есть ли (обратно совместимый?!) способ использовать что-то вроде Throwables.propagate(), который устанавливает поток как прерванный, если он обертывает и распространяет InterruptedException?


person Aled Sage    schedule 10.10.2012    source источник
comment
Я бы поднял это как запрос функции в Guava.   -  person artbristol    schedule 10.10.2012


Ответы (1)


Удобно, мы обсуждали это внутри некоторое время назад. Я просто скопирую и вставлю:

Мое жесткое мнение о Throwables.propagate(e) заключается в том, что это в основном throw new RuntimeException(e) и что люди обычно не должны этого делать, так же как они обычно не должны писать throw new RuntimeException(e). (И если они собираются написать это, они могут также написать это прямо, чтобы было ясно, что происходит.)

Мое бескомпромиссное мнение о catch (Exception e) (как обычно люди ввязываются в эту неразбериху) состоит в том, что обычно они тоже не должны этого делать. (Очевидно, что есть случаи, в которых catch (Exception e), очевидно, является правильным решением (в основном любой блок catch верхнего уровня, область действия), но это... очевидно.)

Мое жесткое мнение о InterruptedException заключается в том, что наличие InterruptedException реализации Exception нарушается именно таким образом: оно требует специальной обработки, которой нет в других исключениях.

Мое жесткое мнение о преобразовании InterruptedException в RuntimeException — «не надо». (Это, как и многое другое, что я сказал выше, является спорным.)

Итак, с одной стороны, я не уверен, что мы можем что-то сделать, чтобы спасти propagate(). С другой стороны, может быть, неплохо было бы сделать метод чуть менее плохим.

Затем снова рассмотрим этот вызывающий объект, который перехватывает ExecutionException e:

throw Throwables.propagate(e.getCause());

Было бы неправильно прерывать поток-потребитель, так же как было бы неправильно бросать e.getCause() напрямую, потому что прерывание предназначалось для вычислительного потока, а не для потока-потребителя.

Я склонен оставить propagate() в покое. (Как вы, наверное, догадались, я лично склонен осуждать это, но это более серьезная дискуссия.)

person Chris Povirk    schedule 10.10.2012
comment
+1 интересные моменты. Я поражен, что люди пишут throw Throwables.propagate(e.getCause());! Трассировка стека будет выглядеть так, как будто все произошло в одном потоке! - person artbristol; 10.10.2012
comment
Спасибо, интересные моменты. +1 к InterruptedException, реализующему Exception неправильно, но Java там, где он есть. Я думаю, что преобразование InterruptedException в RuntimeException иногда необходимо: если сигнатура моего метода фиксируется внешним интерфейсом (поэтому я не могу генерировать InterruptedException), и моя операция была прервана (поэтому я не могу выполнить свой контракт), я должен бросить исключение. Какой другой разумный вариант, кроме установки потока как прерванного и создания исключения RuntimeException? - person Aled Sage; 11.10.2012
comment
Для записи throw new RuntimeException(e) вместо этого раздражает наличие исключения, обертывающего исключение (особенно, когда оно не добавляет ничего полезного, например, дополнительного сообщения о текущем контексте). Везде, где этого шума можно избежать (например, это уже непроверенное исключение), тогда отлично. Существует мнение, что API должны использовать непроверенные исключения везде, где это возможно. Даже если кто-то не верит этому аргументу, он все равно должен реализовать чужие интерфейсы, написанные таким образом. Поэтому, пожалуйста, не осуждайте Throwables.propagate(e)! - person Aled Sage; 11.10.2012
comment
Я думаю, что гораздо лучше throw Throwables.propagate(e);, чем добавлять исключение в сигнатуру метода, когда вы имеете дело с API, который генерирует проверенное исключение, которое вы не хотите специально обрабатывать. Я думаю, что это хороший идиоматический способ сказать, что здесь ничего конкретного, рассматривайте это как обычную проблему выполнения. - person Pierre-Henri; 11.10.2012