Java: Unterschied in der Verwendung zwischen Thread.interrupted() und Thread.isInterrupted()?

Lesezeit: 6 Minuten

Benutzer-Avatar
Python-Typ

Java-Frage: Soweit ich weiß, gibt es zwei Möglichkeiten, innerhalb eines Threads zu prüfen, ob der Thread ein Interrupt-Signal erhalten hat, Thread.interrupted() und Thread.isInterrupted()und der einzige Unterschied zwischen ihnen besteht darin, dass ersteres das interne Unterbrechungs-Flag zurücksetzt.

Bisher habe ich immer verwendet Thread.isInterrupted() und hatte nie probleme damit. Andererseits empfehlen die meisten Tutorials, die ich gesehen habe, die Verwendung Thread.interrupted(). Gibt es dafür einen bestimmten Grund?

  • Doug Lee verwendet Thread.interrupted() ausgiebig. Vielleicht sollten Sie Ihren Code posten, der isInterrupted() verwendet, und die Leute überprüfen lassen, ob alles in Ordnung ist

    – unseriös

    14. Dezember 2009 um 23:55 Uhr

Benutzer-Avatar
Michael myers

interrupted() ist static und überprüft den aktuellen Thread. isInterrupted() ist eine Instanzmethode, die die überprüft Thread Objekt, das aufgerufen wird.

Ein häufiger Fehler besteht darin, eine statische Methode für eine Instanz aufzurufen.

Thread myThread = ...;
if (myThread.interrupted()) {} // WRONG! This might not be checking myThread.
if (myThread.isInterrupted()) {} // Right!

Ein weiterer Unterschied besteht darin interrupted() löscht auch den Status des aktuellen Threads. Mit anderen Worten, wenn Sie ihn zweimal hintereinander aufrufen und der Thread zwischen den beiden Aufrufen nicht unterbrochen wird, wird der zweite Aufruf zurückgegeben false auch wenn der erste Anruf kam true.

Das Javadocs Ihnen wichtige Dinge wie diese sagen; benutze sie oft!

Wenn du benutzt interruptedwas Sie fragen, ist “Werde ich seit meiner letzten Frage unterbrochen?”

isInterrupted teilt Ihnen mit, ob der Thread, in dem Sie es aufrufen, derzeit unterbrochen ist.

Das interrupted() method ist eine Klassenmethode, die stets überprüft den aktuellen Thread und löscht das Unterbrechungs-“Flag”. Mit anderen Worten, ein zweiter Anruf an interrupted() wird zurückkehren false.

Das isInterrupted() Methode ist eine Instanzmethode; es meldet den Status des Threads, auf dem es aufgerufen wird. Außerdem wird das Unterbrechungsflag nicht gelöscht. Wenn das Flag gesetzt ist, bleibt es nach Aufruf dieser Methode gesetzt.

Es gibt viele Redewendungen InterruptedExceptionaber die Frage betraf die explizite Überprüfung des unterbrochenen Status.

Mein Verständnis ist das isInterrupted (die Instanzmethode) sollte selten verwendet werden – hauptsächlich zum Protokollieren und Debuggen und dergleichen. Es gibt nur einen Schnappschuss des Flags in einem bestimmten Thread, der bald darauf veraltet sein kann.

Die übliche Redewendung ist zu überprüfen interrupted (die statische Methode), wenn Sie eine Aufgabe schreiben, die an einem bestimmten Punkt, an dem sie sich befindet, abgebrochen werden soll nicht Aufrufen von etwas, das wirft InterruptedException B. aufgrund eines Ruhezustands oder blockierenden E/A-Aufrufs oder dergleichen. Wenn Sie sehen, dass das Flag gesetzt ist, sollten Sie Ihre aktuelle Berechnung so schnell wie möglich stoppen, vorzeitig zurückkehren oder eine Ausnahme auslösen (evtl InterruptedException).

Also als Beispiel, wenn Ihre Aufgabe so aussieht

void process(Things[] things) throws InterruptedException {
    for (Thing thing : things) {
        thing.twiddle(); // this call throws InterruptedException
    }
}

dann brauchen Sie nichts weiter zu tun; wenn jemand anruft Thread.interrupt in Ihrem Thread, während des aktuellen oder nächsten twiddle ruf an InterruptedException wird hochgeschleudert und stoppt deine Aufgabe.

Aber was wenn twiddle tut nicht Wurf InterruptedException und in der Regel nicht in der Mitte unterbrochen werden kann? Angenommen, jeder dieser Anrufe dauert 100 ms, aber things.length könnte 100 sein. Dann process könnte für 10 Sekunden blockiert werden, selbst wenn jemand versucht, sie zu unterbrechen, was in Ihrer Anwendung möglicherweise nicht akzeptabel ist. So können Sie explizit nach Interrupts suchen:

void process(Things[] things) {
    if (Thread.interrupted()) {
        return;
    }
    for (Thing thing : things) {
        thing.twiddle();
    }
}

Hier können Sie sehen, warum das wichtig ist interrupted überprüft und löscht das Flag atomar: Sie verwenden es, um den Empfang einer Nachricht zu bestätigen, dass jemand Sie höflich gebeten hat, so schnell wie möglich aufzuhören. (In diesem Fall innerhalb von etwa 100 ms nach der Anfrage.) Sie können auch sehen, warum dies eine statische Methode sein muss, die auf dem aktuellen Thread arbeitet: Sie ist nur im Zusammenhang mit der Überprüfung sinnvoll, ob der umgebende Code gestoppt werden soll.

Natürlich, wenn der Anrufer von process geht einfach davon aus, dass es bis zur Fertigstellung gelaufen ist returnEine Darstellung wie hier gezeigt wäre irreführend. So möchten Sie vielleicht machen process gibt die Anzahl der Dinge zurück, die es fertig verarbeitet hat, oder es könnte einfach angemessener sein, die Ausnahme auszulösen:

void process(Things[] things) throws InterruptedException {
    if (Thread.interrupted()) {
        throw new InterruptedException();
    }
    for (Thing thing : things) {
        thing.twiddle();
    }
}

In diesem Fall erhält der Aufrufer eine (geprüfte) Ausnahme, die ihn darüber informiert, dass jemand anderes darum gebeten hat, die Verarbeitung mittendrin zu stoppen. Normalerweise sollte der Aufrufer die Ausnahme einfach in den Aufrufstapel werfen lassen.

Sie könnten sich auch selbst wieder unterbrechen, wenn Sie Ihre aktuelle Aufgabe nicht beenden konnten, aber wissen mussten, dass eine Anfrage zum Stoppen eingegangen ist, beispielsweise um den Rest der Arbeit abzukürzen:

void process(Things[] things) {
    boolean twiddleFully = true;
    if (twiddleFully && Thread.interrupted()) {
        twiddleFully = false;
        Thread.currentThread().interrupt();
    }
    for (Thing thing : things) {
        thing.twiddle(twiddleFully);
    }
}

Hier können wir die verbleibenden Dinge schneller verarbeiten, aber trotzdem die Schleife vervollständigen und das unterbrochene Flag wieder aktivieren, damit unser Aufrufer entscheiden kann, es zu handhaben.

Benutzer-Avatar
Dekan Povey

Thread-Unterbrechung in Java ist ratsam. Wenn Sie Thread.interrupt() aufrufen, wird das Flag gesetzt und alle ausstehenden IO-Aufgaben abgebrochen (was InterruptedException auslöst). Es ist jedoch Sache des Codes, der im Thread ausgeführt wird, dies zu handhaben. Dies wird als Implementieren der Thread-Unterbrechungsrichtlinie bezeichnet.

Da der unterbrochene Zustand von Thread jedoch gemeinsam genutzt wird, ist es wichtig, dass eine solche Behandlung Thread-sicher ist. Sie möchten nicht, dass ein anderer Thread losgeht und versucht, etwas mit dem unterbrochenen Flag zu tun, wenn Sie es behandeln. Aus diesem Grund macht das Thread.interrupted()-Flag dies atomar, sodass es verwendet wird, wenn Sie sagen möchten: „Wenn dieser Thread unterbrochen wurde, werde ich mich darum kümmern). Normalerweise beinhaltet dies das Bereinigen einiger Ressourcen Wenn Sie fertig sind, sollten Sie wahrscheinlich das Interrupt-Flag weitergeben, damit Aufrufer damit umgehen können.Sie können dies tun, indem Sie Thread.interrupt erneut aufrufen.

Benutzer-Avatar
Bob Cross

Hier sind ein paar Beispiele dafür, wie Sie diese Methoden verwenden können:

  1. Wenn Sie Ihren eigenen Thread-Pool schreiben, möchten Sie möglicherweise den Unterbrechungsstatus eines der von Ihnen verwalteten Threads überprüfen. In diesem Fall würden Sie anrufen managedThread.isInterrupted() um den Unterbrechungsstatus zu überprüfen.

  2. Wenn Sie Ihre eigenen InterruptedException-Handler schreiben, die nicht sofort eine entsprechende Ausnahme per erneut auslösen Thread.currentThread().interrupt() (z. B. könnten Sie einen finally-Block nach Ihren Exception-Handlern haben), möchten Sie vielleicht überprüfen, ob dieser Thread, den Sie gerade ausführen, durch einen externen Aufruf oder InterruptedException unterbrochen wurde. In diesem Fall würden Sie den booleschen Wert von überprüfen Thread.interrupted() um den Status Ihres aktuellen Threads zu überprüfen.

Die zweite Methode ist für mich wirklich nur in Situationen nützlich, in denen ich befürchte, dass jemand auf einer niedrigeren Ebene einen Ausnahmefresser geschrieben hat, der dadurch auch eine InterruptedException gefressen hat.

Die Methode interrupt() ist eine statische Methode der Klasse Thread, die den aktuellen Thread überprüft und das Unterbrechungs-“Flag” löscht, dh ein zweiter Aufruf von interrupt() gibt false zurück.

Die Methode isInterrupted() ist eine Instanzmethode; es meldet den Status des Threads, auf dem es aufgerufen wird. es löscht das Unterbrechungsflag nicht.

Wenn das Flag gesetzt ist, bleibt es nach Aufruf dieser Methode gesetzt.

Thread myThread = ...;
if (myThread.interrupted()) {} //error

Thread.interrupted()//right

if (myThread.isInterrupted()) {} // Right

1103400cookie-checkJava: Unterschied in der Verwendung zwischen Thread.interrupted() und Thread.isInterrupted()?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy