Der Thread-Interrupt-Mechanismus ist der bevorzugte Weg, um einen (kooperierenden) Thread dazu zu bringen, auf eine Anfrage zu antworten, um zu stoppen, was er tut. Jeder Thread (einschließlich des Threads selbst, denke ich) könnte interrupt()
einen Thread aufrufen .
In der Praxis umfassen die normalen Anwendungsfälle interrupt()
eine Art Framework oder Manager, der einem Arbeitsthread sagt, er solle aufhören, was er tut. Wenn der Worker-Thread "Interrupt-fähig" ist, wird er feststellen, dass er durch eine Ausnahme oder durch regelmäßige Überprüfung seines unterbrochenen Flags unterbrochen wurde. Wenn ein gut erzogener Thread bemerkt, dass er unterbrochen wurde, gibt er auf, was er tut, und beendet sich selbst.
Unter der Annahme des obigen Anwendungsfalls wird Ihr Code wahrscheinlich unterbrochen, wenn er in einem Java-Framework oder in einem Arbeitsthread ausgeführt wird. Und wenn es unterbrochen wird, sollte Ihr Code aufgeben, was er tut, und sich mit den am besten geeigneten Mitteln selbst beenden. Abhängig davon, wie Ihr Code aufgerufen wurde, kann dies durch Zurückgeben oder durch Auslösen einer geeigneten Ausnahme erfolgen. Aber es sollte wohl nicht anrufen System.exit()
. (Ihre Anwendung weiß nicht unbedingt, warum sie unterbrochen wurde, und sie weiß sicherlich nicht, ob andere Threads vom Framework unterbrochen werden müssen.)
Wenn Ihr Code jedoch nicht für die Ausführung unter einem bestimmten Framework ausgelegt ist, können Sie argumentieren, dass dies InterruptedException
eine unerwartete Ausnahme ist. dh ein Fehler. In diesem Fall sollten Sie die Ausnahme wie andere Fehler behandeln. Binden Sie es beispielsweise in eine nicht aktivierte Ausnahme ein und fangen Sie es an derselben Stelle ab und protokollieren Sie es, an der Sie sich mit anderen unerwarteten nicht aktivierten Ausnahmen befassen. (Alternativ kann Ihre Anwendung den Interrupt einfach ignorieren und das tun, was sie getan hat.)
1) Was kann eine InterruptedException auslösen, wenn ich niemals andere Threads selbst unterbreche?
Ein Beispiel ist, wenn Ihre Runnable
Objekte mit einem ausgeführt werden ExecutorService
und shutdownNow()
im Dienst aufgerufen werden. Und theoretisch könnte jeder Thread-Pool oder jedes Thread-Management-Framework eines Drittanbieters legitimerweise so etwas tun.
2) Wenn ich niemals selbst andere Threads mit Interrupt () unterbreche ... was bedeutet ein InterruptedException
dann? Was soll ich tun, wenn ich einen fange? App herunterfahren?
Sie müssen die Codebasis analysieren, um herauszufinden, was die interrupt()
Anrufe tätigt und warum. Sobald Sie das herausgefunden haben, können Sie herausfinden, was >> Ihr << Teil der App tun muss.
Bis Sie wissen, warum InterruptedException
geworfen wird, würde ich empfehlen, es als einen schweren Fehler zu behandeln; Drucken Sie beispielsweise 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 Fehler" 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 dem festzulegen Thread.interrupt()
und den Aufrufstapel zu betrachten.
Wie andere bereits betont haben, wird das Unterbrechen eines Threads (tatsächlich das Unterbrechen eines blockierenden Anrufs) normalerweise zum sauberen Beenden oder zum Abbrechen einer laufenden Aktivität verwendet.
Sie sollten einen
InterruptedException
allein jedoch nicht als "Beenden-Befehl" behandeln. Stattdessen sollten Sie sich Interrupts als Mittel vorstellen, um den laufenden Status von Threads zu steuern, ähnlich wie dies derObject.notify()
Fall ist. Auf die gleiche Weise, wie Sie den aktuellen Status nach dem Aufwachen von einem Anruf an überprüfen würdenObject.wait()
(Sie gehen nicht davon aus, dass das Aufwecken bedeutet, dass Ihre Wartebedingung erfüllt ist), sollten Sie nach einem Anstoß mit einem Interrupt überprüfen, warum Sie unterbrochen wurden . Es gibt normalerweise einen Weg, dies zu tun. Hat zum Beispieljava.util.concurrent.FutureTask
eineisCancelled()
Methode.Codebeispiel:
quelle
Das Problem mit der Frage ist "Ich". "Ich" bezieht sich normalerweise auf eine einzelne Instanz einer Klasse. Ich meine damit, dass ein bestimmtes Stück Code (Klasse) auf niedriger Ebene nicht auf der Implementierung des gesamten Systems beruhen sollte. Allerdings müssen Sie einige "architektonische" Entscheidungen treffen (z. B. auf welcher Plattform ausgeführt werden soll).
Mögliche unerwartete Interrupts, die von der JRE kommen, sind abgebrochene Aufgaben in
java.util.concurrent
und das Herunterfahren von Applets.Die Behandlung von Thread-Interrupts wird normalerweise falsch geschrieben. Daher schlage ich die architektonische Entscheidung vor, nach Möglichkeit keine Interrupts zu verursachen. Code-Handling-Interrupts sollten jedoch immer korrekt geschrieben werden. Interrupts können jetzt nicht aus der Plattform entfernt werden.
quelle
Sie können dies lernen, indem Sie eine eigene Thread-Klasse (Erweiterung
java.lang.Thread
) und eine überschreibendeinterrupt()
Methode erstellen , in der Sie den Stacktrace beispielsweise in ein String-Feld aufzeichnen und dann an super.interrupt () übertragen.quelle
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 die Liste der ausgeführten Threads abrufen und sie auf diese Weise mit der folgenden Methode unterbrechen .
quelle
Ich glaube, ich verstehe, warum Sie wegen der Unterbrechung etwas verwirrt sind. Bitte beachten Sie meine Antworten in der Zeile:
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. Dies bedeutet, dass Ihr Code, der möglicherweise in einem beliebigen Thread ausgeführt wird, keine Unterbrechung verarbeiten sollte, da er nicht der Eigentümer des Threads ist und keine Ahnung von seiner Unterbrechungsrichtlinie hat. Sie können also eine Unterbrechung für andere Threads anfordern, aber den Eigentümer die Unterbrechungsaktion ausführen lassen. Darin ist die Unterbrechungsrichtlinie enthalten, nicht Ihr Aufgabencode. Sei zumindest höflich, das Unterbrechungsflag zu setzen!
Es gibt viele Möglichkeiten, warum es immer noch zu Unterbrechungen, Zeitüberschreitungen, JVM-Unterbrechungen usw. kommen kann.
Sie müssen hier sehr vorsichtig sein; Wenn Sie den Thread besitzen, der InterruptedException (IE) ausgelöst hat, wissen Sie, was zu tun ist, wenn Sie ihn abfangen. Sagen Sie, Sie können Ihre App / Ihren Dienst herunterfahren oder diesen getöteten Thread durch einen neuen ersetzen! Wenn Sie den Thread jedoch nicht besitzen, werfen Sie ihn beim Abfangen des IE entweder höher im Aufrufstapel oder nachdem Sie etwas getan haben (möglicherweise protokolliert), setzen Sie den unterbrochenen Status zurück, damit der Code, dem dieser Thread gehört, wenn die Steuerung ihn erreicht, dies kann Erfahren Sie, dass der Thread unterbrochen wurde, und ergreifen Sie daher die erforderlichen Aktionen, da nur er die Unterbrechungsrichtlinie kennt.
Hoffe das hat geholfen.
quelle
Das
InterruptedException
besagt , dass eine Routine kann unterbrochen werden, aber nicht unbedingt , dass es sein wird.Wenn Sie den Interrupt nicht erwarten, sollten Sie ihn wie jede andere unerwartete Ausnahme behandeln. Wenn es sich in einem kritischen Bereich befindet, in dem eine unerwartete Ausnahme abscheuliche Folgen haben kann, ist es möglicherweise am besten, Ressourcen zu bereinigen und ordnungsgemäß herunterzufahren (da das Abrufen der Interrupts signalisiert, dass Ihre ausgereifte Anwendung verwendet wird, die nicht auf Interrupts angewiesen ist in gewisser Weise war es nicht entworfen, und so muss etwas falsch sein). Wenn der betreffende Code nicht kritisch oder trivial ist, können Sie den Interrupt ignorieren (oder protokollieren) und weitermachen.
quelle