Відповіді:
Це робиться для утримання держави .
Коли ви ловите InterruptException
та проковтуєте його, ви по суті заважаєте будь-яким методам / групам ниток більш високого рівня помітити переривання. Що може спричинити проблеми.
Зателефонувавши Thread.currentThread().interrupt()
, ви встановлюєте прапор переривання потоку, тому обробники переривань вищого рівня помітять його та можуть належним чином обробити його.
Конкурс Java на практиці обговорює це більш докладно в Розділі 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();
}
}
Спробуйте зателефонувати без перерви, не повертаючи статус.
Примітка:
Як зупинити потік, який довго чекає (наприклад, для введення)?
Щоб ця методика працювала, дуже важливо, щоб будь-який метод, який сприймає виняток переривання і не готовий з цим боротися, негайно підтверджує виняток. Ми кажемо, що це повторно, а не повторно, тому що не завжди можливо повторно скинути виняток. Якщо метод, який ловить InterruptException, не оголошений, щоб викинути цей (перевірений) виняток, він повинен "перезавантажити себе" з наступним закликом:
Thread.currentThread().interrupt();
Це гарантує, що Нитка перейме наново перерваний InterxException, як тільки зможе.
Я вважав би це поганою практикою або хоча б трохи ризикованою. Зазвичай методи вищого рівня не виконують операцій блокування, і вони ніколи не побачатьInterruptedException
там . Якщо ви маскуєте його в кожному місці, коли ви виконуєте операцію з перериванням, ви її ніколи не отримаєте.
Єдине обґрунтування Thread.currentThread.interrupt()
та не викликає будь-якого іншого винятку чи сигналізації запиту на переривання будь-яким іншим способом (наприклад, встановлення interrupted
локальної змінної змінної у головному циклі потоку) - це ситуація, коли ви дійсно нічого не можете зробити за винятком, як у finally
блоках.
Дивіться відповідь Петера Тьорка, якщо ви хочете краще зрозуміти наслідки Thread.currentThread.interrupt()
дзвінка.
Зверніться до java doc
Якщо цей потік заблокований у виклику wait (), join (), sleep (long), то його стан переривання буде очищено, і він отримає InterruptException.
Якщо цей потік заблокований в операції вводу / виводу, буде встановлено статус переривання потоку, і потік отримає ClosedByInterruptException.
Якщо цей потік заблокований у селекторі, то буде встановлено стан переривання потоку і він негайно повернеться з операції вибору.
Якщо жодна з попередніх умов не виконується, буде встановлено статус переривання цього потоку.
Отже, якщо ви змінили метод sleepBabySleep () в @Ajay George Answer to I / O Operation або просто систематизації, вам не доведеться повертати стан, щоб зупинити програму. (До речі, вони навіть не кидають InterruptException)
Так, як сказав @ Péter Török => Це робиться для збереження стану. (Зокрема, для методу, який викине InterruptException)
InterruptedException
статусу переривання, коли він це робить. Я думаю, що це робить відповідь зрозумілішою з точки зору того, чому потрібно зберегти статус переривання."