Что делает java.lang.Thread.interrupt()?
Не могли бы вы объяснить, что java.lang.Thread.interrupt()
когда вызывается?
10 ответов
Thread.interrupt()
устанавливает прерванный статус / флаг целевого потока. Затем код, выполняющийся в этом целевом потоке, МОЖЕТ опрашивать прерванное состояние и обрабатывать его соответствующим образом. Некоторые методы, которые блокируют, такие как Object.wait()
может немедленно использовать прерванный статус и выдать соответствующее исключение (обычно InterruptedException
)
Прерывание в Java не является преимущественным. Иными словами, оба потока должны взаимодействовать, чтобы правильно обработать прерывание. Если целевой поток не опрашивает прерванное состояние, прерывание фактически игнорируется.
Опрос происходит через Thread.interrupted()
метод, который возвращает статус прерывания текущего потока И очищает этот флаг прерывания. Обычно поток может сделать что-то, например, бросить InterruptedException.
РЕДАКТИРОВАТЬ (из комментариев Thilo): Некоторые методы API имеют встроенную обработку прерываний. Из верхней части моей головы это включает в себя.
Object.wait()/Thread.sleep()
- Наиболее
java.util.concurrent
сооружения - Java NIO (но не java.io) и он НЕ использует
InterruptedException
вместо использованияClosedByInterruptException
,
РЕДАКТИРОВАТЬ (из Thomas Pornin ответа 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;
}
}
Прерывание потока основано на статусе прерывания флага. Для каждого потока значение по умолчанию статуса прерывания установлено в false. Когда метод interrupt() вызывается в потоке, статус прерывания устанавливается в true.
- Если состояние прерывания = true (interrupt() уже вызвано в потоке), этот конкретный поток не может перейти в спящий режим. Если в этом потоке вызывается sleep, то генерируется прерванное исключение. После выдачи исключения флаг снова становится ложным.
- Если поток уже спит и вызывается interrupt(), поток выйдет из спящего состояния и выдаст прерванное исключение.
Thread.interrupt()
устанавливает прерванный статус / флаг целевого потока в значение true, которое при проверке с использованием Thread.interrupted()
может помочь остановить бесконечную нить. См. http://www.yegor256.com/2015/10/20/interrupted-exception.html
Метод Thread.interrupt() устанавливает внутренний флаг "статус прерывания". Обычно этот флаг проверяется методом Thread.interrupted().
По соглашению любой метод, который существует через InterruptedException, должен очистить флаг состояния прерывания.
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
Я хочу добавить одну или две вещи к приведенным выше ответам.
Следует помнить, что вызов метода прерывания не всегда приводит к
InterruptedException
. Таким образом, реализующий код должен периодически проверять статус прерывания и предпринимать соответствующие действия.Thread.currentThread().isInterrupted()
также может использоваться для проверки статуса прерывания потока. в отличие отThread.interrupted()
метод, он не очищает статус прерывания.