InterruptedException ist möglicherweise nicht so einfach, wie Sie denken!
Wenn wir die Methode „wait()“ eines Java-Objekts oder die Methode „sleep()“ eines Threads aufrufen, müssen wir die Ausnahme „InterruptedException“ abfangen und behandeln. Wenn wir InterruptedException nicht ordnungsgemäß behandeln, treten unerwartete Konsequenzen auf!
Im folgenden Programmcode implementiert die InterruptedTask-Klasse beispielsweise die Runnable-Schnittstelle. In der run()-Methode wird das Handle des aktuellen Threads und in der while(true)-Schleife das aktuelle abgerufen Der Thread wird über die Methode isInterrupted () erkannt. Wenn der aktuelle Thread unterbrochen ist, wird die while(true)-Schleife verlassen. Gleichzeitig gibt es auch eine Zeile in der while(true)-Schleife Thread.sleep(100)-Code und die InterruptedException-Ausnahme wird erfasst.
Der gesamte Code wird unten angezeigt.
package io.binghe.concurrent.lab08; /** * @author binghe * @version 1.0.0 * @description 线程测试中断 */ public class InterruptedTask implements Runnable{ @Override public void run() { Thread currentThread = Thread.currentThread(); while (true){ if(currentThread.isInterrupted()){ break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Die ursprüngliche Absicht des obigen Codes besteht darin, mit der Methode isInterrupted() zu prüfen, ob der Thread unterbrochen wurde, und die while-Schleife zu verlassen, wenn er unterbrochen wird. Andere Threads unterbrechen den Ausführungsthread, indem sie die Interrupt()-Methode des Ausführungsthreads aufrufen. Zu diesem Zeitpunkt wird das Interrupt-Flag-Bit des Ausführungsthreads gesetzt, sodass currentThread.isInterrupted() true zurückgibt, sodass die while-Schleife ausgeführt werden kann verlassen.
Das scheint kein Problem zu sein! Aber ist das wirklich so? Wir erstellen zum Testen eine InterruptedTest-Klasse. Der Code lautet wie folgt.
package io.binghe.concurrent.lab08; /** * @author binghe * @version 1.0.0 * @description 测试线程中断 */ public class InterruptedTest { public static void main(String[] args){ InterruptedTask interruptedTask = new InterruptedTask(); Thread interruptedThread = new Thread(interruptedTask); interruptedThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } interruptedThread.interrupt(); } }
Wir führen die Hauptmethode wie unten gezeigt aus.
Der obige Code ruft eindeutig die Interrupt()-Methode des Threads auf, um den Thread zu unterbrechen, hat jedoch keine Auswirkung. Der Grund dafür ist, dass die run()-Methode des Threads die meiste Zeit bei Sleep(100) blockiert wird. Wenn andere Threads den Ausführungsthread durch Aufrufen der interrupt()-Methode des Ausführungsthreads unterbrechen, wird eine InterruptedException ausgelöst Ausnahme: Wenn die InterruptedException-Ausnahme ausgelöst wird, löscht die JVM gleichzeitig das Interrupt-Flag-Bit des Threads. Daher gibt die zu diesem Zeitpunkt in der run()-Methode beurteilte Funktion „Falsch“ zurück. und die aktuelle while-Schleife wird nicht beendet.
Nachdem die Problemanalyse abgeschlossen ist, wie unterbreche ich den Thread und beende das Programm?
Der richtige Weg, damit umzugehen, sollte darin bestehen, die Ausnahme in der while(true)-Schleife in der run()-Methode in der InterruptedTask-Klasse abzufangen und dann das Interrupt-Flag-Bit zurückzusetzen, also die Korrekter Code der InterruptedTask-Klasse Wie unten gezeigt.
package io.binghe.concurrent.lab08; /** * @author binghe * @version 1.0.0 * @description 中断线程测试 */ public class InterruptedTask implements Runnable{ @Override public void run() { Thread currentThread = Thread.currentThread(); while (true){ if(currentThread.isInterrupted()){ break; } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); currentThread.interrupt(); } } } }
Wie Sie sehen können, haben wir im Catch-Codeblock eine neue Codezeile hinzugefügt, die die InterruptedException-Ausnahme erfasst.
currentThread.interrupt();
Dadurch können wir nach dem Abfangen der InterruptedException-Ausnahme das Interrupt-Flag-Bit des Threads zurücksetzen und so den aktuell ausgeführten Thread unterbrechen.
Wir führen die Hauptmethode der InterruptedTest-Klasse erneut aus, wie unten gezeigt.
Seien Sie vorsichtig bei der Behandlung von InterruptedException. Wenn beim Aufrufen der InterruptedException-Methode des Ausführungsthreads eine InterruptedException ausgelöst wird, unterbricht die JVM gleichzeitig die InterruptedException-Ausnahme Das Interrupt-Flag-Bit wird gelöscht, wenn die isInterrupted()-Methode des Ausführungsthreads aufgerufen wird.
Zu diesem Zeitpunkt besteht die richtige Vorgehensweise darin, die InterruptedException-Ausnahme in der run()-Methode des Ausführungsthreads abzufangen und das Interrupt-Flag-Bit zurückzusetzen (d. h. im Catch-Codeblock, der die InterruptedException-Ausnahme abfängt). -Rufen Sie die Interrupt()-Methode des aktuellen Threads auf.
Das obige ist der detaillierte Inhalt vonSo lösen Sie das Problem der InterruptedException mit hoher Parallelität in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!