Чи можете ви пояснити, що java.lang.Thread.interrupt()
робити при виклику?
Чи можете ви пояснити, що java.lang.Thread.interrupt()
робити при виклику?
Відповіді:
Thread.interrupt()
встановлює перерваний стан / прапор цільового потоку. Потім код, що працює в цільовому потоці, МОЖЕ опитувати стан перерви та обробляти його відповідним чином. Деякі методи, що блокують такі, як, Object.wait()
можливо, негайно споживають перерваний стан і видають відповідний виняток (як правило InterruptedException
)
Перерва в Java не є вигідною. По-іншому, обидві нитки повинні співпрацювати, щоб обробити переривання належним чином. Якщо цільовий потік не запитує статус переривання, переривання ефективно ігнорується.
Опитування відбувається за допомогою Thread.interrupted()
методу, який повертає статус поточного перерваного потоку І очищує прапор переривання. Зазвичай потік може потім зробити щось таке, як кинути InterruptException.
EDIT (з коментарів Thilo): Деякі методи API вбудовані в обробці переривань. Серед верхньої частини моєї голови це включає.
Object.wait()
, Thread.sleep()
ІThread.join()
java.util.concurrent
структурInterruptedException
, а використовує ClosedByInterruptException
.EDIT (з відповіді @ thomas-pornin на точно той же питання для повноти)
Переривання нитки - щадний спосіб просунути нитку. Він використовується для того, щоб дати ниткам можливість вийти чисто , на відміну від того, Thread.stop()
що більше нагадує стрілянину з нитки штурмовою гвинтівкою.
Що таке переривання?
Переривання - це вказівка потоці, що вона повинна зупинити те, що вона робить, і зробити щось інше. Програміст повинен вирішити, як саме потік реагує на переривання, але дуже часто зустрічається поток.
Як це реалізується?
Механізм переривання реалізується за допомогою внутрішнього прапора, відомого як статус переривання. Invoking Thread.interrupt встановлює цей прапор. Коли потік перевіряє наявність переривання шляхом виклику статичного методу Thread.interrupt, стан переривання очищається. Нестатичний Thread.isInterrupt, який використовується одним потоком для запиту стану переривання іншим, не змінює прапор статусу переривання.
Цитата від Thread.interrupt()
API :
Перериває цю нитку. Спочатку викликається метод checkAccess цього потоку, що може спричинити перекидання SecurityException.
Якщо цей потік заблокований у виклику методу wait (), wait (long) або wait (long, int) методів класу Object, або of join (), join (long), join (long, int) , сон (довгий) або сон (довгий, int), методи цього класу, тоді його статус переривання буде очищено, і він отримає InterruptException.
Якщо цей потік блокується в операції вводу / виводу на переривному каналі, то канал буде закритий, буде встановлено статус переривання потоку, і потік отримає ClosedByInterruptException.
Якщо цей потік заблокований у селекторі, то буде встановлено статус переривання потоку, і він негайно повернеться з операції вибору, можливо, з ненульовим значенням, так само, як якщо б викликали метод пробудження селектора.
Якщо жодна з попередніх умов не виконується, буде встановлено статус переривання цього потоку.
Перевірте це для повного розуміння приблизно того ж:
http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Якщо цільовий потік чекав (за допомогою виклику wait()
або інших пов'язаних з ним методів, які по суті роблять те саме, як, наприклад sleep()
), він буде перерваний, це означає, що він перестає чекати того, що його чекав, і отримає замість нього InterruptException.
Саме wait()
вирішувати, що робити в цій ситуації, залежить від самої нитки (коду, який зателефонував ). Він автоматично не припиняє потік.
Іноді використовується в поєднанні з прапором припинення. При перерві нитка може перевірити цей прапор, а потім закрити себе. Але знову ж таки, це лише умовність.
Для повноти, крім інших відповідей, якщо нитка переривається до того, як вона блокується на Object.wait(..)
або Thread.sleep(..)
т.п., це рівносильно тому, що вона переривається негайно при блокуванні цього методу , як показано в наступному прикладі.
public class InterruptTest {
public static void main(String[] args) {
Thread.currentThread().interrupt();
printInterrupted(1);
Object o = new Object();
try {
synchronized (o) {
printInterrupted(2);
System.out.printf("A Time %d\n", System.currentTimeMillis());
o.wait(100);
System.out.printf("B Time %d\n", System.currentTimeMillis());
}
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("C Time %d\n", System.currentTimeMillis());
printInterrupted(3);
Thread.currentThread().interrupt();
printInterrupted(4);
try {
System.out.printf("D Time %d\n", System.currentTimeMillis());
Thread.sleep(100);
System.out.printf("E Time %d\n", System.currentTimeMillis());
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("F Time %d\n", System.currentTimeMillis());
printInterrupted(5);
try {
System.out.printf("G Time %d\n", System.currentTimeMillis());
Thread.sleep(100);
System.out.printf("H Time %d\n", System.currentTimeMillis());
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("I Time %d\n", System.currentTimeMillis());
}
static void printInterrupted(int n) {
System.out.printf("(%d) Am I interrupted? %s\n", n,
Thread.currentThread().isInterrupted() ? "Yes" : "No");
}
}
Вихід:
$ javac InterruptTest.java
$ java -classpath "." InterruptTest
(1) Am I interrupted? Yes
(2) Am I interrupted? Yes
A Time 1399207408543
WAS interrupted
C Time 1399207408543
(3) Am I interrupted? No
(4) Am I interrupted? Yes
D Time 1399207408544
WAS interrupted
F Time 1399207408544
(5) Am I interrupted? No
G Time 1399207408545
H Time 1399207408668
I Time 1399207408669
Послідовність: якщо ви перебуваєте в циклі, як описано нижче, і переривання відбувається в той самий момент, коли контроль пішов Thread.sleep(..)
і збирається навколо циклу, виняток все одно відбуватиметься. Тож цілком безпечно розраховувати на те, що InterruptException надійно закидається після переривання нитки :
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
break;
}
}
Thread.interrupt()
встановлює перерваний статус / прапор цільового потоку на істинне, що при перевірці за допомогою Thread.interrupted()
може допомогти зупинити нескінченну нитку. Зверніться до http://www.yegor256.com/2015/10/20/interrupt-exception.html
Переривання нитки базується на статусі переривання прапора . Для кожного потоку значення за замовчуванням статусу переривання встановлюється на хибне . Щоразу, коли метод потоку переривання () викликається в потоці, статус переривання встановлюється на істинне .
публічне недійсне переривання ()
Перериває цю нитку.
Якщо поточний потік не перериває себе, що завжди дозволено, використовується метод checkAccess цього потоку, що може спричинити перекидання SecurityException.
Якщо цей потік заблокований у виклику методу wait (), wait (long) або wait (long, int) методів класу Object, або of join (), join (long), join (long, int) , сон (довгий) або сон (довгий, int), методи цього класу, тоді його статус переривання буде очищено, і він отримає InterruptException.
Якщо цей потік блокується в операції вводу / виводу на переривному каналі, то канал буде закритий, буде встановлено статус переривання потоку, і потік отримає ClosedByInterruptException.
Якщо цей потік заблокований у селекторі, то буде встановлено статус переривання потоку, і він негайно повернеться з операції вибору, можливо, з ненульовим значенням, так само, як якщо б викликали метод пробудження селектора.
Якщо жодна з попередніх умов не виконується, буде встановлено статус переривання цього потоку.
Переривання живої нитки не потребує жодного ефекту.
Throw: SecurityException - якщо поточний потік не може змінити цей потік
Переривання - це вказівка потоці, що вона повинна зупинити те, що вона робить, і зробити щось інше. Програміст повинен вирішити, як саме потік реагує на переривання, але дуже часто, що нитка закінчується. Дуже хороший референс: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Метод Thread.interrupt () встановлює внутрішній прапор 'статусу переривання'. Зазвичай цей прапор перевіряється методом Thread.interrupted ().
За умовою, будь-який метод, який існує за допомогою InterruptException, повинен очистити прапор статусу переривання.