Ответы:
Это сделано, чтобы сохранить состояние .
Когда вы ловите InterruptException
и проглатываете его, вы по существу не допускаете, чтобы любые методы / группы потоков более высокого уровня замечали прерывание. Что может вызвать проблемы.
Вызывая Thread.currentThread().interrupt()
, вы устанавливаете флаг прерывания потока, так что обработчики прерываний более высокого уровня заметят это и могут обработать это соответствующим образом.
Java Concurrency на практике обсуждает это более подробно в главе 7.1.3: Реагирование на прерывание . Его правило таково:
Только код, который реализует политику прерывания потока, может проглотить запрос прерывания. Универсальный код задачи и библиотеки никогда не должен поглощать запросы прерывания.
interrupt()
вызов - это единственный способ установить флаг прерывания, как только вы получили уведомление об этом состоянии через другой «механизм доставки» - InterruptedException
и он желает или не может повторно его выбросить.
Я думаю, что этот пример кода проясняет ситуацию. Класс, который делает работу:
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();
}
}
Попробуйте вызвать прерывание без возврата статуса.
Примечание:
Как мне остановить поток, который ждет в течение длительного времени (например, для ввода)?
Чтобы этот метод работал, очень важно, чтобы любой метод, который перехватывает исключение прерывания и не готов обработать его, немедленно переустанавливает исключение. Мы говорим, скорее, подтверждает, а не отбрасывает, потому что не всегда возможно отбросить исключение. Если метод, который перехватывает InterruptedException, не объявлен для генерирования этого (проверенного) исключения, то он должен «сам себя прервать» следующим заклинанием:
Thread.currentThread().interrupt();
Это гарантирует, что Поток повторно вызовет InterruptedException, как только сможет.
Я бы посчитал это плохой практикой или хотя бы немного рискованной. Обычно методы более высокого уровня не выполняют блокирующих операций и никогда их InterruptedException
там не увидят . Если вы маскируете его в каждом месте, где выполняете прерываемую операцию, вы никогда не получите его.
Единственное обоснование Thread.currentThread.interrupt()
и отсутствие вызова любого другого исключения или запроса прерывания каким-либо другим способом (например, установка interrupted
переменной локальной переменной в главном цикле потока) - это ситуация, когда вы действительно ничего не можете сделать с исключением, как в finally
блоках.
См. Ответ Петера Тёрока, если вы хотите лучше понять значение этого Thread.currentThread.interrupt()
звонка.
См. Документ Java
Если этот поток заблокирован при вызове wait (), join (), sleep (long), то его состояние прерывания будет очищено, и он получит исключение InterruptedException.
Если этот поток заблокирован в операции ввода-вывода, состояние прерывания потока будет установлено, и поток получит исключение ClosedByInterruptException.
Если этот поток заблокирован в селекторе, то будет установлено состояние прерывания потока, и он немедленно вернется из операции выбора.
Если ни одно из предыдущих условий не выполняется, то состояние прерывания этого потока будет установлено.
Итак, если вы измените метод sleepBabySleep () в @Ajay George Ответ на операцию ввода-вывода или просто на sysout, вам не нужно возвращать статус обратно, чтобы остановить программу. (Кстати, они даже не генерируют InterruptedException)
Точно так же, как сказал @ Петер Тёрёк => Это сделано для сохранения состояния. (И особенно для метода, который будет генерировать InterruptedException)
InterruptedException
очищенное состояние прерывания, когда это делает. Я думаю, что это делает ответ более понятным с точки зрения того, почему вам нужно сохранять состояние прерывания.