Что делает java.lang.Thread.interrupt ()?

Ответы:

251

Thread.interrupt()устанавливает прерванный статус / флаг целевого потока. Затем код, выполняющийся в этом целевом потоке, МОЖЕТ опрашивать прерванное состояние и обрабатывать его соответствующим образом. Некоторые методы, которые блокируют, такие как, Object.wait()могут немедленно потреблять прерванное состояние и выдавать соответствующее исключение (обычно InterruptedException)

Прерывание в Java не является преимущественным. Иными словами, оба потока должны взаимодействовать, чтобы правильно обработать прерывание. Если целевой поток не опрашивает прерванное состояние, прерывание фактически игнорируется.

Опрос происходит с помощью Thread.interrupted()метода, который возвращает статус прерывания текущего потока И очищает этот флаг прерывания. Обычно поток может затем сделать что-то, например, бросить InterruptedException.

РЕДАКТИРОВАТЬ (из комментариев Thilo): Некоторые методы API имеют встроенную обработку прерываний. Из верхней части моей головы это включает в себя.

  • Object.wait(), Thread.sleep()ИThread.join()
  • Большинство java.util.concurrentструктур
  • Java NIO (но не java.io), и он НЕ использует InterruptedException, а не использует ClosedByInterruptException.

РЕДАКТИРОВАТЬ (от полноты ответа @ thomas-pornin на тот же вопрос )

Прерывание нити - это мягкий способ подтолкнуть нить. Он используется, чтобы дать возможность нитям выйти чистого , в отличие от того, Thread.stop()что больше похоже на стрельбу из винтовки.

Майк Q
источник
22
Обратите внимание, что такие методы, как sleep или wait, выполняют такой опрос и генерируют InterruptedException самостоятельно.
Тило
1
Если вы используете прерывистый файловый ввод / вывод, эффект не будет таким мягким. Обычно вы получаете повреждение файла.
Марко Топольник
если вы упоминаете Thread.interrupted, похоже, следует упомянуть, что есть также флаг Thread.isInterrupted, который не очищает флаг, что обычно делает его более подходящим для использования разработчиками приложений.
Натан Хьюз
67

Что такое прерывание?

Прерывание - это указание потоку, что он должен остановить то, что он делает, и сделать что-то еще. Программист должен решить, как именно поток реагирует на прерывание, но очень часто поток завершается.

Как это реализовано?

Механизм прерывания реализован с использованием внутреннего флага, известного как статус прерывания. Вызов 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

СВО
источник
Это подчиняется частичному объяснению. Это также прерывает прерываемые методы.
маркиз Лорн
@EJP Этот вопрос о том, что такое метод Thread.interrupt () и как он работает. Я думаю, что все, что я отправил со ссылкой, отвечает на то, что спрашивают. Я до сих пор не понимаю, чего ты хочешь?
Йок
Я хочу, чтобы вы исправили ваше частично неверное утверждение, что оно реализуется флагом. Это только часть истории. Это кажется мне совершенно ясным.
маркиз Лорн
@EJP Спасибо. Теперь я понимаю, что вы говорили. Я обновил свой ответ и добавил документ API для метода. Это касается части прерываемых методов, которая отсутствовала в моем ответе. Надеюсь, мой ответ выглядит полным :).
2010 года
13

Если целевой поток ожидал (вызывая wait()или с помощью других связанных методов, которые, по сути, делают то же самое, например sleep()), он будет прерван, что означает, что он перестает ожидать того, что ожидал, и вместо этого получает InterruptedException.

Это полностью зависит от самого потока (код, который вызвал wait()), чтобы решить, что делать в этой ситуации. Это не автоматически завершает поток.

Иногда используется в сочетании с флагом завершения. При прерывании поток может проверить этот флаг, а затем отключиться. Но опять же, это просто соглашение.

Тило
источник
9 лет, нестареющий ответ! +1
ОСШ
10

Для полноты, в дополнение к другим ответам, если поток прерывается до того, как он блокируется 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;
    }
}
Евгений Сергеев
источник
4

Thread.interrupt()устанавливает прерванный статус / флаг целевого потока в значение true, что при проверке с помощью Thread.interrupted()может помочь остановить бесконечный поток. См. Http://www.yegor256.com/2015/10/20/interrupted-exception.html

Санчи Джиротра
источник
4

Прерывание потока основано на статусе прерывания флага . Для каждого потока значение по умолчанию статуса прерывания установлено в false . Всякий раз, когда метод interrupt () вызывается в потоке, статус прерывания устанавливается равным true .

  1. Если статус прерывания = true (interrupt () уже вызван в потоке), этот конкретный поток не может перейти в спящий режим. Если в этом потоке вызывается sleep, то генерируется прерванное исключение. После выдачи исключения флаг снова становится ложным.
  2. Если поток уже спит и вызывается interrupt () , поток выйдет из спящего состояния и выдаст прерванное исключение.
акаш г
источник
1

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 - если текущий поток не может изменить этот поток

Аджит Ганга
источник
1

Прерывание - это указание потоку, что он должен остановить то, что он делает, и сделать что-то еще. Программист должен решить, как именно поток реагирует на прерывание, но очень часто поток завершается. Очень хорошая ссылка: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

Adi
источник
1

Метод Thread.interrupt () устанавливает внутренний флаг «статус прерывания». Обычно этот флаг проверяется методом Thread.interrupted ().

По соглашению любой метод, который существует через InterruptedException, должен очистить флаг состояния прерывания.

Анатолий Шуба
источник