Frage Wer ruft die Java-Thread interrupt () -Methode auf, wenn ich nicht bin?


Ich habe Java Concurrency in der Praxis gelesen und wiedergelesen, ich habe hier einige Threads zum Thema gelesen, ich habe den IBM Artikel gelesen Umgang mit InterruptedException und doch gibt es etwas, das ich einfach nicht verstehe und das meiner Meinung nach in zwei Fragen aufgeteilt werden kann:

  1. Wenn ich selbst niemals andere Threads störe, was kann einen auslösen InterruptedException?

  2. Wenn ich niemals andere Threads selbst benutze unterbrechen() (Sagen wir, weil ich andere Methoden benutze, um meine Arbeitsfäden abzubrechen, wie Giftpillen und während (! abgebrochen) Style-Loop [wie beide in JCIP erklärt]), was macht ein InterruptedException dann gemein? Was soll ich tun, wenn ich einen fange? Herunterfahren meiner App?


76
2018-01-24 12:25


Ursprung


Antworten:


Der Thread-Interrupt-Mechanismus ist der bevorzugte Weg, um einen (kooperierenden) Thread dazu zu bringen, auf eine Anfrage zu reagieren, um zu stoppen, was er tut. Jeder Thread (einschließlich des Threads selbst, denke ich) könnte anrufen interrupt() auf einem Thread.

In der Praxis sind die normalen Anwendungsfälle für interrupt() involvieren irgendeine Art von Framework oder Manager, der einem Worker-Thread mitteilt, was er gerade macht. Wenn der Worker-Thread "interrupt aware" ist, wird er bemerken, dass er durch eine Ausnahme unterbrochen wurde, oder indem er sein unterbrochenes Flag periodisch überprüft. Als er bemerkte, dass es unterbrochen worden war, würde ein braver Faden aufgeben, was er tut, und sich selbst beenden.

Unter der Annahme des obigen Anwendungsfalls wird Ihr Code wahrscheinlich unterbrochen, wenn er innerhalb eines Java-Frameworks oder aus einem Worker-Thread ausgeführt wird. Und wenn es unterbrochen wird, sollte Ihr Code das, was er tut, aufgeben und sich selbst mit den am besten geeigneten Mitteln beenden. Abhängig davon, wie der Code aufgerufen wurde, kann dies durch Zurückgeben oder durch Auslösen einer entsprechenden Ausnahme geschehen. Aber es sollte wahrscheinlich nicht anrufen System.exit(). (Ihre Anwendung weiß nicht unbedingt, warum sie unterbrochen wurde, und sie weiß nicht, ob andere Threads vom Framework unterbrochen werden müssen.)

Auf der anderen Seite, wenn Ihr Code nicht unter der Kontrolle eines Frameworks ausgeführt wird, könnten Sie argumentieren, dass InterruptedException ist eine unerwartete Ausnahme; ein Fehler. In diesem Fall sollten Sie die Ausnahme wie andere Fehler behandeln. z.B. Umschließen Sie es in einer nicht aktivierten Ausnahme und fangen Sie es an derselben Stelle ab, an der Sie andere unerwartete ungeprüfte Ausnahmen behandeln. (Alternativ könnte Ihre Anwendung den Interrupt einfach ignorieren und weiterhin tun, was sie gerade tut.)


1) Wenn ich niemals selbst andere Threads störe, was kann eine InterruptedException auslösen?

Ein Beispiel ist, wenn Sie Runnable Objekte werden mit einem ausgeführt ExecutorService und shutdownNow() wird auf den Dienst gerufen. Und in der Theorie könnte jeder Thread-Pool oder Thread-Management-Framework eines Drittanbieters in etwa so etwas tun.

2) Wenn ich niemals andere Threads mit interrupt () unterbrechen werde ... was macht ein InterruptedExceptiondann gemein? Was soll ich tun, wenn ich einen fange? Herunterfahren meiner App?

Sie müssen die Codebasis analysieren, um herauszufinden, was das macht interrupt() Anrufe und warum. Sobald Sie das herausgefunden haben, können Sie herausfinden, was >> Ihr << Teil der App tun soll.

Bis du weißt warum InterruptedException Wird geworfen, würde ich empfehlen, es als einen schweren Fehler zu behandeln; z.B. Drucken Sie einen Stacktrace in die Protokolldatei und fahren Sie die App herunter. (Natürlich ist das nicht immer die richtige Antwort ... aber der Punkt ist, dass dies ein "Bug" ist und der Entwickler / Betreuer darauf aufmerksam gemacht werden muss.)

3) Wie finde ich heraus, wer / was anruft? interrupt()?

Darauf gibt es keine gute Antwort. Das Beste, was ich vorschlagen kann, ist einen Haltepunkt auf der Thread.interrupt() und schauen Sie sich den Call-Stack an.


44
2018-01-24 14:41



Wenn Sie Ihren Code in andere Bibliotheken integrieren möchten, können Sie ihn anrufen interrupt() auf deinem Code. z.B. wenn Sie sich in Zukunft dazu entschließen, Ihren Code innerhalb eines ExecutorServiceDann kann das eine Abschaltung erzwingen interrupt().

Um es kurz zu machen, würde ich nicht nur daran denken, wo der Code läuft jetzt, aber in welchem ​​Kontext kann es in der Zukunft laufen. z.B. Wirst du es in eine Bibliothek stellen? Ein Container ? Wie werden andere Leute es benutzen? Wirst du es wiederverwenden?


12
2018-01-24 12:43



Wie andere darauf hingewiesen haben, wird das Unterbrechen eines Threads (eigentlich das Unterbrechen eines blockierenden Anrufs) normalerweise dazu verwendet, sauber zu beenden oder eine laufende Aktivität abzubrechen.

Sie sollten jedoch nicht ein InterruptedException allein als "quit command". Stattdessen sollten Sie sich Interrupts als Mittel zum Steuern des Ausführungsstatus von Threads vorstellen, ähnlich wie Object.notify() tut. Genauso wie Sie den aktuellen Status nach dem Aufwachen von einem Anruf an überprüfen würden Object.wait() (Sie gehen nicht davon aus, dass das Aufwachen bedeutet, dass Ihre Wartebedingung erfüllt wurde.) Nachdem Sie mit einem Interrupt gestupst wurden, sollten Sie dies überprüfen Warum Du wurdest unterbrochen. Es gibt normalerweise einen Weg, dies zu tun. Beispielsweise, java.util.concurrent.FutureTask hat ein isCancelled() Methode.

Codebeispiel:

public void run() {
    ....
    try {
        .... // Calls that may block.
    } catch (InterruptedException e) {
        if (!running) {  // Add preferred synchronization here.
            return; // Explicit flag says we should stop running.
        }
        // We were interrupted, but the flag says we're still running.
        // It would be wrong to always exit here. The interrupt 'nudge'
        // could mean something completely different. For example, it
        // could be that the thread was blocking on a read from a particular
        // file, and now we should read from a different file.
        // Interrupt != quit (not necessarily).
    }
    ....
}
public void stop() {
    running = false; // Add preferred synchronization here.
    myThread.interrupt();
}

9
2017-10-12 08:38



Das Problem mit der Frage ist "Ich". "I" bezieht sich normalerweise auf eine einzelne Instanz einer Klasse. Ich meine damit, dass irgendein bestimmter Teil des Low-Level-Codes (Klasse) sich nicht auf die Implementierung des gesamten Systems verlassen sollte. Allerdings haben Sie einige "architektonische" Entscheidungen getroffen (wie auf welcher Plattform).

Mögliche unerwartete Interrupts, die von der JRE kommen, sind abgebrochene Tasks in java.util.concurrent und Herunterfahren von Applets.

Die Behandlung von Thread Interrupts wird normalerweise falsch geschrieben. Daher empfehle ich die architektonische Entscheidung, Unterbrechungen möglichst zu vermeiden. Code-Handling-Interrupts sollten jedoch immer korrekt geschrieben werden. Interrupts können jetzt nicht aus der Plattform genommen werden.


3
2018-01-24 16:39



Sie können dies lernen, indem Sie eine eigene Thread-Klasse erstellen (extending) java.lang.Thread) und überschreiben interrupt() Methode, in der Sie den StackTrace beispielsweise in ein String-Feld aufzeichnen und dann an super.interrupt () übergeben.

public class MyThread extends Thread {

    public volatile String interruptStacktrace; // Temporary field for debugging purpose.

    @Override
    public void interrupt() {
        interruptStacktrace = dumpStack(); // You implement it somehow...

        super.interrupt();
    }
}

2
2017-11-12 11:02



Wie bereits erwähnt, kann eine andere Bibliothek Ihre Threads unterbrechen. Auch wenn die Bibliothek keinen expliziten Zugriff auf die Threads aus Ihrem Code hat, können sie dennoch die Liste der ausgeführten Threads abrufen und sie auf folgende Weise unterbrechen Methode.


1
2018-01-24 18:10



Das InterruptedException sagt das eine Routine kann unterbrochen werden, aber nicht unbedingt, dass es sein wird.

Wenn Sie den Interrupt nicht erwarten, sollten Sie ihn wie eine andere unerwartete Ausnahme behandeln. Wenn es sich um einen kritischen Abschnitt handelt, in dem eine unerwartete Ausnahme schwerwiegende Folgen haben kann, empfiehlt es sich möglicherweise, Ressourcen zu bereinigen und ordnungsgemäß herunterzufahren (da das Interrupt-Signal dafür sorgt, dass Ihre ausgereifte Anwendung nicht auf Interrupts angewiesen ist) in gewisser Weise wurde es nicht entworfen, und deshalb muss etwas falsch sein). Alternativ, wenn der fragliche Code etwas nichtkritisches oder triviales ist, möchten Sie möglicherweise den Interrupt ignorieren (oder loggen) und weitermachen.


0
2018-01-24 13:03



Ich denke, ich verstehe, warum du wegen der Unterbrechung etwas verwirrt bist. Bitte beachte meine Antworten in der Zeile:

Wenn ich selbst niemals andere Threads störe, was kann einen auslösen InterruptedException?

Erstens können Sie andere Threads unterbrechen; Ich weiß, dass in JCiP erwähnt wird, dass Sie niemals Threads unterbrechen sollten, die Sie nicht besitzen; Diese Aussage muss jedoch richtig verstanden werden. Es bedeutet, dass Ihr Code, der in einem beliebigen Thread ausgeführt wird, keine Unterbrechung verarbeiten sollte, da er nicht der Besitzer des Threads ist, er hat keine Ahnung von seiner Unterbrechungsrichtlinie. Sie können also Unterbrechungen bei anderen Threads anfordern, aber lassen Sie den Besitzer die Unterbrechung unterbrechen; Es enthält die Unterbrechungsrichtlinie, nicht den Taskcode. Sei wenigstens höflich, die Unterbrechungsflagge zu setzen!

Es gibt viele Möglichkeiten, warum es Unterbrechungen geben könnte, Timeouts, JVM-Interrupts usw.

Wenn ich niemals andere Threads mit interrupt () unterbrechen würde (zB weil ich andere Methoden nutze, um meine Arbeitsfäden abzubrechen, wie Giftpillen und während (! Canceled) Style Loops [wie in JCIP erklärt]), was bedeutet eine InterruptedException dann? Was soll ich tun, wenn ich einen fange? Herunterfahren meiner App?

Sie müssen hier sehr vorsichtig sein; Wenn Sie den Thread besitzen, der InterruptedException (IE) ausgelöst hat, dann wissen Sie, was zu tun ist, wenn Sie ihn abgefangen haben. Sagen Sie, Sie könnten Ihre App / Ihren Dienst herunterfahren oder Sie können diesen getöteten Thread durch einen neuen ersetzen! Wenn Sie jedoch nicht den Thread besitzen, setzen Sie den unterbrochenen Status zurück, wenn der Internet Explorer den Aufruf-Stack erneut aufruft oder wenn er etwas unternimmt (möglicherweise protokolliert), so dass der Code, dem dieser Thread gehört, wenn die Steuerung ihn erreicht, kann lerne, dass der Thread unterbrochen wurde und daher Maßnahmen ergreifen, da nur er die Unterbrechungsrichtlinie kennt.

Hoffe das hat geholfen.


0
2018-03-20 18:10