Не могли бы вы объяснить, что java.lang.Thread.interrupt()
делает, когда вызывается?
Не могли бы вы объяснить, что java.lang.Thread.interrupt()
делает, когда вызывается?
Ответы:
Thread.interrupt()
устанавливает прерванный статус / флаг целевого потока. Затем код, выполняющийся в этом целевом потоке, МОЖЕТ опрашивать прерванное состояние и обрабатывать его соответствующим образом. Некоторые методы, которые блокируют, такие как, Object.wait()
могут немедленно потреблять прерванное состояние и выдавать соответствующее исключение (обычно InterruptedException
)
Прерывание в Java не является преимущественным. Иными словами, оба потока должны взаимодействовать, чтобы правильно обработать прерывание. Если целевой поток не опрашивает прерванное состояние, прерывание фактически игнорируется.
Опрос происходит с помощью Thread.interrupted()
метода, который возвращает статус прерывания текущего потока И очищает этот флаг прерывания. Обычно поток может затем сделать что-то, например, бросить InterruptedException.
РЕДАКТИРОВАТЬ (из комментариев Thilo): Некоторые методы API имеют встроенную обработку прерываний. Из верхней части моей головы это включает в себя.
Object.wait()
, Thread.sleep()
ИThread.join()
java.util.concurrent
структурInterruptedException
, а не использует ClosedByInterruptException
.РЕДАКТИРОВАТЬ (от полноты ответа @ thomas-pornin на тот же вопрос )
Прерывание нити - это мягкий способ подтолкнуть нить. Он используется, чтобы дать возможность нитям выйти чистого , в отличие от того, Thread.stop()
что больше похоже на стрельбу из винтовки.
Что такое прерывание?
Прерывание - это указание потоку, что он должен остановить то, что он делает, и сделать что-то еще. Программист должен решить, как именно поток реагирует на прерывание, но очень часто поток завершается.
Как это реализовано?
Механизм прерывания реализован с использованием внутреннего флага, известного как статус прерывания. Вызов Thread.interrupt устанавливает этот флаг. Когда поток проверяет наличие прерывания, вызывая статический метод Thread.interrupted, состояние прерывания очищается. Нестатический Thread.isInterrupted, который используется одним потоком для запроса статуса прерывания другого, не изменяет флаг состояния прерывания.
Цитата из Thread.interrupt()
API :
Прерывает эту тему. Сначала вызывается метод checkAccess этого потока, который может вызвать исключение SecurityException.
Если этот поток заблокирован при вызове методов wait (), wait (long) или wait (long, int) класса Object или join (), join (long), join (long, int) , sleep (long) или sleep (long, int), методы этого класса, тогда его состояние прерывания будет очищено, и он получит InterruptedException.
Если этот поток заблокирован в операции ввода-вывода для прерываемого канала, то канал будет закрыт, состояние прерывания потока будет установлено, и поток получит исключение ClosedByInterruptException.
Если этот поток заблокирован в селекторе, то будет установлено состояние прерывания потока, и он немедленно вернется из операции выбора, возможно, с ненулевым значением, как если бы был вызван метод пробуждения селектора.
Если ни одно из предыдущих условий не выполняется, то состояние прерывания этого потока будет установлено.
Проверьте это для полного понимания о том же:
http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Если целевой поток ожидал (вызывая wait()
или с помощью других связанных методов, которые, по сути, делают то же самое, например sleep()
), он будет прерван, что означает, что он перестает ожидать того, что ожидал, и вместо этого получает InterruptedException.
Это полностью зависит от самого потока (код, который вызвал 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(..)
и обходит цикл, исключение все равно будет происходить. Поэтому совершенно безопасно полагаться на то, что InterruptedException будет надежно выдан после прерывания потока :
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
break;
}
}
Thread.interrupt()
устанавливает прерванный статус / флаг целевого потока в значение true, что при проверке с помощью Thread.interrupted()
может помочь остановить бесконечный поток. См. Http://www.yegor256.com/2015/10/20/interrupted-exception.html
Прерывание потока основано на статусе прерывания флага . Для каждого потока значение по умолчанию статуса прерывания установлено в false . Всякий раз, когда метод interrupt () вызывается в потоке, статус прерывания устанавливается равным true .
public void interrupt ()
Прерывает эту тему.
Если текущий поток не прерывает сам себя, что всегда разрешено, вызывается метод checkAccess этого потока, что может привести к возникновению исключения SecurityException.
Если этот поток заблокирован при вызове методов wait (), wait (long) или wait (long, int) класса Object или join (), join (long), join (long, int) , sleep (long) или sleep (long, int), методы этого класса, тогда его состояние прерывания будет очищено, и он получит InterruptedException.
Если этот поток заблокирован в операции ввода-вывода для прерываемого канала, то канал будет закрыт, состояние прерывания потока будет установлено, и поток получит исключение ClosedByInterruptException.
Если этот поток заблокирован в селекторе, то будет установлено состояние прерывания потока, и он немедленно вернется из операции выбора, возможно, с ненулевым значением, как если бы был вызван метод пробуждения селектора.
Если ни одно из предыдущих условий не выполняется, то состояние прерывания этого потока будет установлено.
Прерывание потока, который не является живым, не должно иметь никакого эффекта.
Выдает: SecurityException - если текущий поток не может изменить этот поток
Прерывание - это указание потоку, что он должен остановить то, что он делает, и сделать что-то еще. Программист должен решить, как именно поток реагирует на прерывание, но очень часто поток завершается. Очень хорошая ссылка: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Метод Thread.interrupt () устанавливает внутренний флаг «статус прерывания». Обычно этот флаг проверяется методом Thread.interrupted ().
По соглашению любой метод, который существует через InterruptedException, должен очистить флаг состояния прерывания.