Должен ли я беспокоиться о InterruptedExceptions, если я ничего не прерываю?

Я использую java.util.concurrent.Semaphore в проекте хобби. Он используется в классе пула соединений, который я пишу. Я могу использовать его с небольшой проблемой, кроме этого метода:

public void acquire(int permits) throws InterruptedException

что заставляет меня обрабатывать InterruptedException. Теперь я не уверен, что "прерывание" Thread даже означает, и я никогда не делаю этого (ну, не явно, так или иначе) в моем коде. Означает ли это, что я могу игнорировать исключение? Как я должен справиться с этим?

Ответ 1

Да, вам нужно беспокоиться о InterruptedException, так же как вам нужно беспокоиться о любом другом исключенном исключении, которое вы должны либо бросать, либо обрабатывать.

В большинстве случаев a InterruptedException сигнализирует запрос на остановку, скорее всего, из-за того, что поток, который запускал ваш код, был прерван.

В вашей конкретной ситуации в пуле соединений, ожидающем подключения, я бы сказал, что это проблема отмены, и вам нужно прекратить процесс приобретения, очистки и восстановить прерванный флаг (см. ниже).


В качестве примера, если вы используете какой-то Runnable/Callable, запущенный внутри Executor, вам необходимо правильно обработать прерывание:

executor.execute(new Runnable() {

    public void run() {
         while (true) {
              try {
                 Thread.sleep(1000);
              } catch ( InterruptedException e) {
                  continue; //blah
              }
              pingRemoteServer();
         }
    }
});

Это означало бы, что ваша задача никогда не подчиняется механизму прерывания, используемому исполнителем, и не позволяет надлежащего отмены/завершения работы.

Вместо этого правильная идиома состоит в том, чтобы восстановить прерванный статус и затем остановить выполнение:

executor.execute(new Runnable() {

    public void run() {
         while (true) {
              try {
                 Thread.sleep(1000);
              } catch ( InterruptedException e) {
                  Thread.currentThread().interrupt(); // restore interrupted status
                  break;
              }
              pingRemoteServer();
         }
    }
});

Полезные ресурсы:

Ответ 2

Неа. InterruptedException генерируется только в том случае, если вы сами прерываете поток. Если вы сами не используете Thread.interrupt(), я бы либо перебросил его как "неожиданное исключение", либо зарегистрировал его как ошибку и перешел. Например, в моем коде, когда я вынужден поймать InterruptedException, и я никогда не называю interrupt() сам, я делаю эквивалент

catch (InterruptedException exception) {
    throw new RuntimeException("Unexpected interrupt", exception);
}

Что если это неожиданно. Есть много мест, где я намеренно прерываю свои потоки, и в тех случаях я обрабатываю InterruptedException четко определенным образом. Обычно, выйдя из любого цикла, в котором я зашел, очистка и прекращение потока.

Ответ 3

Потоки могут быть прерваны вызовом Thread.interrupt(). Он используется для изящной сигнализации потока, что он должен делать что-то еще. Обычно это приводит к тому, что операции блокировки (например, Thread.sleep()) возвращаются раньше и вызывают исключение InterruptedException. Если поток прерывается, на нем устанавливается флаг. Этот флаг можно запросить через вызов Thread.isInterrupted().

Если вы не используете прерывание потока и все еще получаете это исключение, вы можете просто выйти из потока (и, лучше всего, зарегистрировать исключение).

В общем, это зависит от того, что делает ваше многопоточное приложение.

Ответ 4

Если вы не знаете, как обрабатывать его в методе, я предлагаю вам объявить его в методе с помощью throw InterruptedException (и его вызывающего и т.д.)

Если это что-то, чего вы никогда не ожидаете, я поймаю его и завершу в AssertionError.

Ответ 5

Вы должны выйти из метода run() после выполнения любой очистки, необходимой для вашего потока.
НТН