Должен ли я беспокоиться о 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() после выполнения любой очистки, необходимой для вашего потока.
НТН