Що робить java.lang.Thread.interrupt ()?


Відповіді:


250

Thread.interrupt()встановлює перерваний стан / прапор цільового потоку. Потім код, що працює в цільовому потоці, МОЖЕ опитувати стан перерви та обробляти його відповідним чином. Деякі методи, що блокують такі, як, Object.wait()можливо, негайно споживають перерваний стан і видають відповідний виняток (як правило InterruptedException)

Перерва в Java не є вигідною. По-іншому, обидві нитки повинні співпрацювати, щоб обробити переривання належним чином. Якщо цільовий потік не запитує статус переривання, переривання ефективно ігнорується.

Опитування відбувається за допомогою Thread.interrupted()методу, який повертає статус поточного перерваного потоку І очищує прапор переривання. Зазвичай потік може потім зробити щось таке, як кинути InterruptException.

EDIT (з коментарів Thilo): Деякі методи API вбудовані в обробці переривань. Серед верхньої частини моєї голови це включає.

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

EDIT (з відповіді @ thomas-pornin на точно той же питання для повноти)

Переривання нитки - щадний спосіб просунути нитку. Він використовується для того, щоб дати ниткам можливість вийти чисто , на відміну від того, Thread.stop()що більше нагадує стрілянину з нитки штурмовою гвинтівкою.


22
Зауважте, що такі способи, як сон або очікування, проводять подібне опитування і передають InterruptException самі.
Тіло

1
Якщо ви використовуєте переривний файл вводу / виводу, ефект не буде таким щадним. Зазвичай ви отримаєте пошкодження файлів.
Марко Тополник

якщо ви згадуєте Thread.interrupted, здається, слід зазначити, що існує також прапор Thread.isInterrupted, який не очищає прапор, що робить його зазвичай більш доцільним для використання розробниками додатків.
Натан Х'юз

67

Що таке переривання?

Переривання - це вказівка ​​потоці, що вона повинна зупинити те, що вона робить, і зробити щось інше. Програміст повинен вирішити, як саме потік реагує на переривання, але дуже часто зустрічається поток.

Як це реалізується?

Механізм переривання реалізується за допомогою внутрішнього прапора, відомого як статус переривання. 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


Це підпорядковується частковому поясненню. Він також перериває переривчасті методи.
Маркіз Лорн

@EJP Це питання про те, що таке метод Thread.interrupt () та як він працює. Я думаю, що все, що я опублікував за посиланням, відповідає на запитання. Я досі не розумію, чого ти хочеш?
YoK

Я бажаю вам виправити частково неправильне твердження про те, що воно реалізовано прапором. Це лише частина історії. Мені це здається цілком зрозумілим.
Маркіз Лорн

@EJP Дякую Тепер я розумію, що ви говорили. Я оновив свою відповідь і додав API для методу API. Це стосується частини переривних методів, якої не було в моїй відповіді. Сподіваюся, моя відповідь зараз виглядає повною :).
Йок

13

Якщо цільовий потік чекав (за допомогою виклику wait()або інших пов'язаних з ним методів, які по суті роблять те саме, як, наприклад sleep()), він буде перерваний, це означає, що він перестає чекати того, що його чекав, і отримає замість нього InterruptException.

Саме 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(..)і збирається навколо циклу, виняток все одно відбуватиметься. Тож цілком безпечно розраховувати на те, що InterruptException надійно закидається після переривання нитки :

while (true) {
    try {
        Thread.sleep(10);
    } catch (InterruptedException ie) {
        break;
    }
}


4

Переривання нитки базується на статусі переривання прапора . Для кожного потоку значення за замовчуванням статусу переривання встановлюється на хибне . Щоразу, коли метод потоку переривання () викликається в потоці, статус переривання встановлюється на істинне .

  1. Якщо статус переривання = true (переривання () вже викликано в потоці), цей конкретний потік не може перейти у режим сну. Якщо сон викликається на цій нитці, переривається виняток. Після викидання винятку знову прапор встановлюється на false.
  2. Якщо нитка вже спить і викликається переривання () , нитка вийде зі сплячого стану та викине перерваний виняток.

1

публічне недійсне переривання ()

Перериває цю нитку.

Якщо поточний потік не перериває себе, що завжди дозволено, використовується метод checkAccess цього потоку, що може спричинити перекидання SecurityException.

Якщо цей потік заблокований у виклику методу wait (), wait (long) або wait (long, int) методів класу Object, або of join (), join (long), join (long, int) , сон (довгий) або сон (довгий, int), методи цього класу, тоді його статус переривання буде очищено, і він отримає InterruptException.

Якщо цей потік блокується в операції вводу / виводу на переривному каналі, то канал буде закритий, буде встановлено статус переривання потоку, і потік отримає ClosedByInterruptException.

Якщо цей потік заблокований у селекторі, то буде встановлено статус переривання потоку, і він негайно повернеться з операції вибору, можливо, з ненульовим значенням, так само, як якщо б викликали метод пробудження селектора.

Якщо жодна з попередніх умов не виконується, буде встановлено статус переривання цього потоку.

Переривання живої нитки не потребує жодного ефекту.

Throw: SecurityException - якщо поточний потік не може змінити цей потік


1

Переривання - це вказівка ​​потоці, що вона повинна зупинити те, що вона робить, і зробити щось інше. Програміст повинен вирішити, як саме потік реагує на переривання, але дуже часто, що нитка закінчується. Дуже хороший референс: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html


1

Метод Thread.interrupt () встановлює внутрішній прапор 'статусу переривання'. Зазвичай цей прапор перевіряється методом Thread.interrupted ().

За умовою, будь-який метод, який існує за допомогою InterruptException, повинен очистити прапор статусу переривання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.