Зачем вызывать метод Thread.currentThread.interrupt() в блоке catch?
Зачем вызывать Thread.currentThread.interrupt() в блоке InterruptException catch?
Ответ 1
Это делается для сохранения состояния.
Когда вы ловите InterruptException
и проглатываете его, вы по существу препятствуете тому, чтобы какие-либо методы более высокого уровня/группы потоков замечали прерывание. Это может вызвать проблемы.
Вызывая Thread.currentThread().interrupt()
, вы устанавливаете флаг прерывания потока, поэтому обработчики прерываний более высокого уровня заметят его и могут обрабатывать его соответствующим образом.
Java Concurrency на практике более подробно обсуждается в главе 7.1.3: Ответ на прерывание. Его правило:
Только код, реализующий политику прерывания потока, может усвоить запрос прерывания. Универсальный код задачи и библиотеки никогда не должен проглатывать запросы прерывания.
Ответ 2
Я думаю, что этот образец кода делает вещи немного ясными. Класс, выполняющий задание:
public class InterruptedSleepingThread extends Thread {
@Override
public void run() {
doAPseudoHeavyWeightJob();
}
private void doAPseudoHeavyWeightJob() {
for (int i=0;i<Integer.MAX_VALUE;i++) {
//You are kidding me
System.out.println(i + " " + i*2);
//Let me sleep <evil grin>
if(Thread.currentThread().isInterrupted()) {
System.out.println("Thread interrupted\n Exiting...");
break;
}else {
sleepBabySleep();
}
}
}
/**
*
*/
protected void sleepBabySleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
Основной класс:
public class InterruptedSleepingThreadMain {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
InterruptedSleepingThread thread = new InterruptedSleepingThread();
thread.start();
//Giving 10 seconds to finish the job.
Thread.sleep(10000);
//Let me interrupt
thread.interrupt();
}
}
Попробуйте вызвать прерывание, не устанавливая статус.
Ответ 3
Примечание:
Как остановить поток, который ожидает длительные периоды (например, для ввода)?
Для того, чтобы этот метод работал, критически важно, чтобы любой метод, который ловил исключение прерывания и не был готов к его устранению, немедленно повторяет исключение. Мы говорим о повторных попытках, а не о повторениях, потому что не всегда можно перестроить исключение. Если метод, который улавливает InterruptedException, не объявляется, чтобы выбрасывать это (отмеченное) исключение, тогда он должен "перевоспитать себя" следующим заклинанием:
Thread.currentThread().interrupt();
Это гарантирует, что Thread будет ререйзить InterruptedException, как только он сможет.
Ответ 4
Я считаю это плохой практикой или, по крайней мере, немного рискованно.
Обычно методы более высокого уровня не выполняют блокирующие операции, и они никогда не будут видеть InterruptedException
. Если вы замаскируете его во всех местах, где вы выполняете прерывистую операцию, вы никогда не получите его.
Единственное логическое обоснование для Thread.currentThread.interrupt()
и не возбуждение какого-либо другого запроса об исключении или сигнальном прерывании любым другим способом (например, установка локальной переменной переменной interrupted
в основной петле потока) - это ситуация, когда вы действительно ничего не можете сделать за исключением, как в блоках finally
.
См. ответ Péter Török, если вы хотите лучше понять последствия вызова Thread.currentThread.interrupt()
.