Was macht java.lang.Thread.interrupt ()?

Antworten:

250

Thread.interrupt()setzt den unterbrochenen Status / Flag des Ziel-Threads. Dann kann Code, der in diesem Zielthread ausgeführt wird, den unterbrochenen Status abfragen und entsprechend behandeln. Einige Methoden, die blockieren, wie z. B., Object.wait()können den unterbrochenen Status sofort verbrauchen und (normalerweise InterruptedException) eine entsprechende Ausnahme auslösen.

Eine Unterbrechung in Java ist nicht präventiv. Anders ausgedrückt, beide Threads müssen zusammenarbeiten, um den Interrupt ordnungsgemäß zu verarbeiten. Wenn der Ziel-Thread den unterbrochenen Status nicht abfragt, wird der Interrupt effektiv ignoriert.

Das Abrufen erfolgt über die Thread.interrupted()Methode, die den unterbrochenen Status des aktuellen Threads zurückgibt UND dieses Interrupt-Flag löscht. Normalerweise kann der Thread dann beispielsweise InterruptedException auslösen.

BEARBEITEN (aus Thilo-Kommentaren): Einige API-Methoden haben eine Interrupt-Behandlung eingebaut. Von der Oberseite meines Kopfes schließt dies ein.

  • Object.wait(), Thread.sleep()UndThread.join()
  • Die meisten java.util.concurrentStrukturen
  • Java NIO (aber nicht java.io) und es wird NICHT verwendet InterruptedException, sondern verwendet ClosedByInterruptException.

BEARBEITEN (der Vollständigkeit halber von @ thomas-pornins Antwort auf genau dieselbe Frage )

Eine Fadenunterbrechung ist eine sanfte Methode, um einen Faden anzutreiben. Es wird verwendet, um Fäden die Möglichkeit zu geben, sauber auszutreten , im Gegensatz dazu Thread.stop()eher wie das Schießen des Fadens mit einem Sturmgewehr.

Mike Q.
quelle
22
Beachten Sie, dass Methoden wie sleep oder wait diese Art der Abfrage durchführen und InterruptedException selbst auslösen.
Thilo
1
Wenn Sie unterbrechbare Datei-E / A verwenden, ist der Effekt nicht so sanft. In der Regel wird die Datei beschädigt.
Marko Topolnik
Wenn Sie Thread.interrupted erwähnen, sollte anscheinend erwähnt werden, dass es auch ein Thread.isInterrupted-Flag gibt, das das Flag nicht löscht, wodurch es normalerweise für die Verwendung durch Anwendungsentwickler besser geeignet ist.
Nathan Hughes
67

Was ist Interrupt?

Ein Interrupt ist ein Hinweis für einen Thread, dass er aufhören soll, was er tut, und etwas anderes tun soll. Es ist Sache des Programmierers, genau zu entscheiden, wie ein Thread auf einen Interrupt reagiert. Es kommt jedoch häufig vor, dass der Thread beendet wird.

Wie ist es implementiert?

Der Interrupt-Mechanismus wird unter Verwendung eines internen Flags implementiert, das als Interrupt-Status bekannt ist. Durch Aufrufen von Thread.interrupt wird dieses Flag gesetzt. Wenn ein Thread durch Aufrufen der statischen Methode Thread.interrupted nach einem Interrupt sucht, wird der Interrupt-Status gelöscht. Der nicht statische Thread.isInterrupted, der von einem Thread zum Abfragen des Interrupt-Status eines anderen Threads verwendet wird, ändert das Interrupt-Status-Flag nicht.

Zitat aus der Thread.interrupt()API :

Unterbricht diesen Thread. Zuerst wird die checkAccess-Methode dieses Threads aufgerufen, wodurch möglicherweise eine SecurityException ausgelöst wird.

Wenn dieser Thread bei einem Aufruf der Methoden wait (), wait (long) oder wait (long, int) der Object-Klasse oder der join (), join (long), join (long, int) blockiert ist. , sleep (long) oder sleep (long, int), Methoden dieser Klasse, dann wird ihr Interrupt-Status gelöscht und es wird eine InterruptedException empfangen.

Wenn dieser Thread in einer E / A-Operation auf einem unterbrechbaren Kanal blockiert wird, wird der Kanal geschlossen, der Interrupt-Status des Threads wird festgelegt und der Thread erhält eine ClosedByInterruptException.

Wenn dieser Thread in einem Selektor blockiert ist, wird der Interrupt-Status des Threads gesetzt und er kehrt sofort von der Auswahloperation zurück, möglicherweise mit einem Wert ungleich Null, so als ob die Aufweckmethode des Selektors aufgerufen worden wäre.

Wenn keine der vorherigen Bedingungen erfüllt ist, wird der Interrupt-Status dieses Threads festgelegt.

Überprüfen Sie dies für ein vollständiges Verständnis darüber:

http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

YoK
quelle
Dies ist eine teilweise Erklärung. Es unterbricht auch unterbrechbare Methoden.
Marquis von Lorne
@EJP Bei dieser Frage geht es darum, was die Thread.interrupt () -Methode ist und wie sie funktioniert. Ich denke, was auch immer ich mit Link gepostet habe, beantwortet, was gefragt wird. Ich verstehe immer noch nicht, was Sie sich wünschen?
YoK
Ich möchte, dass Sie Ihre teilweise falsche Aussage korrigieren, dass sie durch ein Flag implementiert wird. Das ist nur ein Teil der Geschichte. Es scheint mir ziemlich klar zu sein.
Marquis von Lorne
@ EJP Danke. Jetzt verstehe ich, was du gesagt hast. Ich habe meine Antwort aktualisiert und API-Dokument für Methode hinzugefügt. Dies umfasst einen Teil der unterbrechbaren Methoden, der in meiner Antwort fehlte. Hoffe meine Antwort sieht jetzt komplett aus :).
YoK
13

Wenn der Ziel-Thread gewartet hat (durch Aufrufen wait()oder andere verwandte Methoden, die im Wesentlichen dasselbe tun, wie z. B. sleep()), wird er unterbrochen, was bedeutet, dass er nicht mehr auf das wartet, worauf er gewartet hat, und stattdessen eine InterruptedException empfängt.

Es liegt ganz beim Thread selbst (dem aufgerufenen Code wait()), zu entscheiden, was in dieser Situation zu tun ist. Der Thread wird nicht automatisch beendet.

Es wird manchmal in Kombination mit einem Beendigungsflag verwendet. Bei einer Unterbrechung könnte der Thread dieses Flag überprüfen und sich dann selbst herunterfahren. Aber auch dies ist nur eine Konvention.

Thilo
quelle
9 Jahre alte, zeitlose Antwort! +1
snr
10

Der Vollständigkeit halber zusätzlich zu den anderen Antworten, wenn der Faden , bevor er blockiert unterbrochen : Object.wait(..)oder Thread.sleep(..)usw. Dies entspricht es ist unmittelbar an diesem Verfahren unterbrochen wird bei der Blockierung , wie das folgende Beispiel zeigt.

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");
    }
}

Ausgabe:

$ 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

Implikation: Wenn Sie eine Schleife wie die folgende ausführen und der Interrupt genau zu dem Zeitpunkt auftritt, zu dem die Steuerung verlassen wurde Thread.sleep(..)und die Schleife umrundet, tritt die Ausnahme weiterhin auf. Es ist also absolut sicher, dass die InterruptedException nach dem Unterbrechen des Threads zuverlässig ausgelöst wird :

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

Die Thread-Unterbrechung basiert auf dem Flag- Interrupt-Status . Für jeden Thread wird der Standardwert für den Interrupt-Status auf false gesetzt . Immer wenn die Interrupt () -Methode für einen Thread aufgerufen wird, wird der Interrupt-Status auf true gesetzt .

  1. Wenn der Interrupt-Status = true ist (Interrupt (), der bereits für den Thread aufgerufen wurde), kann dieser bestimmte Thread nicht in den Ruhezustand versetzt werden. Wenn für diesen Thread der Ruhezustand aufgerufen wird, wird eine unterbrochene Ausnahme ausgelöst. Nach dem erneuten Auslösen der Ausnahme wird das Flag auf false gesetzt.
  2. Wenn der Thread bereits schläft und Interrupt () aufgerufen wird, verlässt der Thread den Ruhezustand und löst eine unterbrochene Ausnahme aus.
akash G.
quelle
1

public void Interrupt ()

Unterbricht diesen Thread.

Sofern sich der aktuelle Thread nicht selbst unterbricht, was immer zulässig ist, wird die checkAccess-Methode dieses Threads aufgerufen, wodurch möglicherweise eine SecurityException ausgelöst wird.

Wenn dieser Thread bei einem Aufruf der Methoden wait (), wait (long) oder wait (long, int) der Object-Klasse oder der join (), join (long), join (long, int) blockiert ist. , sleep (long) oder sleep (long, int), Methoden dieser Klasse, dann wird ihr Interrupt-Status gelöscht und es wird eine InterruptedException empfangen.

Wenn dieser Thread in einer E / A-Operation auf einem unterbrechbaren Kanal blockiert wird, wird der Kanal geschlossen, der Interrupt-Status des Threads wird festgelegt und der Thread erhält eine ClosedByInterruptException.

Wenn dieser Thread in einem Selektor blockiert ist, wird der Interrupt-Status des Threads gesetzt und er kehrt sofort von der Auswahloperation zurück, möglicherweise mit einem Wert ungleich Null, so als ob die Aufweckmethode des Selektors aufgerufen worden wäre.

Wenn keine der vorherigen Bedingungen erfüllt ist, wird der Interrupt-Status dieses Threads festgelegt.

Das Unterbrechen eines Threads, der nicht aktiv ist, muss keine Auswirkungen haben.

Auslöser: SecurityException - Wenn der aktuelle Thread diesen Thread nicht ändern kann

Ajeet Ganga
quelle
1

Ein Interrupt ist ein Hinweis für einen Thread, dass er aufhören soll, was er tut, und etwas anderes tun soll. Es ist Sache des Programmierers, genau zu entscheiden, wie ein Thread auf einen Interrupt reagiert. Es kommt jedoch häufig vor, dass der Thread beendet wird. Eine sehr gute Referenz: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

Adi
quelle
1

Die Methode Thread.interrupt () setzt das interne Flag 'Interrupt Status'. Normalerweise wird dieses Flag von der Thread.interrupted () -Methode überprüft.

Gemäß der Konvention muss jede Methode, die über InterruptedException existiert, das Interrupt-Status-Flag löschen.

Anatoliy Shuba
quelle