1. Einführung
In diesem Artikel werden einige Wissenspunkte zum Interrupt-Mechanismus im JAVA-Multithreading aufgeführt. Hauptsächlich die Unterschiede zwischen der Stop-Methode, den Methoden interrupted() und isInterrupted() sowie eine einfache Analyse aus der Implementierung des Quellcodes.
Es gibt drei Möglichkeiten, einen laufenden Thread in JAVA zu beenden
①Der Thread wird normal beendet, das heißt, die run()-Methode wurde ausgeführt
②Verwenden Sie stop im Thread Die Methode class() beendet den Thread zwangsweise. Die stop()-Methode ist jedoch abgelaufen und wird nicht empfohlen.
③ Verwenden Sie den Interrupt-Mechanismus.
Es ist nichts Falsches daran, den Thread normal zu beenden. Der Interrupt-Mechanismus wird im Folgenden ausführlich vorgestellt. Schauen wir uns zunächst den Quellcode der stop()-Methode an. Der Schlüssel liegt in den Kommentaren zum Quellcode. Es erklärt, warum stop() unsicher ist. Welchen Thread stoppt die stop()-Methode?
/** * Forces the thread to stop executing. * <p> * If there is a security manager installed, its <code>checkAccess</code> * method is called with <code>this</code> * as its argument. This may result in a * <code>SecurityException</code> being raised (in the current thread). * <p> * If this thread is different from the current thread (that is, the current * thread is trying to stop a thread other than itself), the * security manager's <code>checkPermission</code> method (with a * <code>RuntimePermission("stopThread")</code> argument) is called in * addition. * Again, this may result in throwing a * <code>SecurityException</code> (in the current thread). * <p> * The thread represented by this thread is forced to stop whatever * it is doing abnormally and to throw a newly created * <code>ThreadDeath</code> object as an exception. * <p> * It is permitted to stop a thread that has not yet been started. * If the thread is eventually started, it immediately terminates. * <p> * An application should not normally try to catch * <code>ThreadDeath</code> unless it must do some extraordinary * cleanup operation (note that the throwing of * <code>ThreadDeath</code> causes <code>finally</code> clauses of * <code>try</code> statements to be executed before the thread * officially dies). If a <code>catch</code> clause catches a * <code>ThreadDeath</code> object, it is important to rethrow the * object so that the thread actually dies. * <p> * The top-level error handler that reacts to otherwise uncaught * exceptions does not print out a message or otherwise notify the * application if the uncaught exception is an instance of * <code>ThreadDeath</code>. * * @exception SecurityException if the current thread cannot * modify this thread. * @see #interrupt() * @see #checkAccess() * @see #run() * @see #start() * @see ThreadDeath * @see ThreadGroup#uncaughtException(Thread,Throwable) * @see SecurityManager#checkAccess(Thread) * @see SecurityManager#checkPermission * @deprecated This method is inherently unsafe. Stopping a thread with * Thread.stop causes it to unlock all of the monitors that it * has locked (as a natural consequence of the unchecked * <code>ThreadDeath</code> exception propagating up the stack). If * any of the objects previously protected by these monitors were in * an inconsistent state, the damaged objects become visible to * other threads, potentially resulting in arbitrary behavior. Many * uses of <code>stop</code> should be replaced by code that simply * modifies some variable to indicate that the target thread should * stop running. The target thread should check this variable * regularly, and return from its run method in an orderly fashion * if the variable indicates that it is to stop running. If the * target thread waits for long periods (on a condition variable, * for example), the <code>interrupt</code> method should be used to * interrupt the wait. * For more information, see * <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why * are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>. */ @Deprecated public final void stop() { stop(new ThreadDeath()); }
Der obige Kommentar, Zeilen 9 bis 16, zeigt an, dass die stop()-Methode „andere Threads“ stoppen kann. Der Thread, der die Anweisung der Methode thread.stop() ausführt, wird als aktueller Thread bezeichnet, und „andere Threads“ sind die Threads, die durch den Objektthread dargestellt werden, der die Methode thread.stop() aufruft.
Zum Beispiel:
public static void main(String[] args) { MyThread thread = new MyThread... //..... thread.stop(); //.... }
In der Hauptmethode ist der aktuelle Thread der Hauptthread. Es wird bis Zeile 4 ausgeführt und möchte den „anderen Thread“-Thread stoppen. Dieser andere Thread ist der Thread, der durch das Thread-Objekt der neuen MyThread-Klasse dargestellt wird.
Die Zeilen 21 bis 23 zeigen an, dass einer gestoppt werden kann Ein Thread, der noch nicht gestartet wurde, ist: Wenn der Thread gestartet wird, wird er sofort beendet. Die Kommentare nach Zeile 48 von
zeigen deutlich, warum die stop()-Methode veraltet ist ?
Der ThreadA-Thread verfügt beispielsweise über Monitore, die für den Schutz bestimmter kritischer Ressourcen verantwortlich sind, z. B. des Betrags einer Banküberweisung, wenn der Haupt-Thread gerade Geld überweist. )-Methode. Dadurch wird der Monitor freigegeben und die von ihm geschützten Ressourcen (Übertragungsbetrag) sind wahrscheinlich inkonsistent. Konto A verringert sich beispielsweise um 100, Konto B erhöht sich jedoch nicht um 100 Zweitens, der Unterbrechungsmechanismus
Es gibt zu viele Details zur korrekten Verwendung des Unterbrechungsmechanismus in JAVA. Die Methode interrupted() und die Methode isInterrupted() geben beide an, ob sich der aktuelle Thread in einem unterbrochenen Zustand befindet ①interrupted()
Wie aus den Kommentaren im Quellcode ersichtlich ist, testet es den Unterbrechungsstatus des aktuellen Threads und diese Methode löscht den Unterbrechungsstatus ②isInterrupted( )/** * Tests whether the current thread has been interrupted. The * <i>interrupted status</i> of the thread is cleared by this method. In * other words, if this method were to be called twice in succession, the * second call would return false (unless the current thread were * interrupted again, after the first call had cleared its interrupted * status and before the second call had examined it). * * <p>A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return <code>true</code> if the current thread has been interrupted; * <code>false</code> otherwise. * @see #isInterrupted() * @revised . */ public static boolean interrupted() { return currentThread().isInterrupted(true); }Wie aus den Quellcodekommentaren ersichtlich ist, löscht die Methode isInterrupted() den Interrupt-Status nicht ③Der Unterschied zwischen der Methode interrupted() und der isInterrupted()-Methode
/** * Tests whether this thread has been interrupted. The <i>interrupted * status</i> of the thread is unaffected by this method. * * <p>A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return <code>true</code> if this thread has been interrupted; * <code>false</code> otherwise. * @see #interrupted() * @revised . */ public boolean isInterrupted() { return isInterrupted(false); }
Wie aus dem Quellcode ersichtlich ist, rufen beide Methoden isInterrupted(boolean ClearInterrupted) auf, aber ein Parameter ist wahr und der andere Parameter ist falsch. Daher besteht der erste Unterschied darin, dass einer gelöscht wird das Interrupt-Flag-Bit und das andere löscht das Interrupt-Flag-Bit nicht
Wenn Sie den Quellcode analysieren, können Sie sehen, dass der zweite Unterschied in der Return-Anweisung liegt:
unterbrochen () testet den Unterbrechungsstatus des aktuellen Threads, während isInterrupted() den Thread testet, der durch das Objekt dargestellt wird, das diese Methode aufruft. Eine davon ist eine statische Methode (sie testet den Unterbrechungsstatus des aktuellen Threads)./** * Tests if some Thread has been interrupted. The interrupted state * is reset or not based on the value of ClearInterrupted that is * passed. */ private native boolean isInterrupted(boolean ClearInterrupted);
Im Folgenden wird ein spezifisches Beispiel verwendet, um diesen Unterschied weiter zu verdeutlichen.
Es gibt eine Anpassung der Thread-Klasse hat die Möglichkeit, die CPU-Ausführung zu erhalten.
public static boolean interrupted() { return currentThread().isInterrupted(true); } /************************/ public boolean isInterrupted() { return isInterrupted(false); }Nachdem der Hauptthread eine Sekunde lang schläft, setzt er die Ausführung in Zeile 7 fort und fordert zur Unterbrechung des Thread-Threads auf. Zeile 9 testet, ob sich der Thread in einem unterbrochenen Zustand befindet. Welcher Thread wird hier getestet? ? ? Die Antwort ist der Hauptthread. Denn: (1) interrupted() testet den Interrupt-Status des aktuellen Threads (2) Der Hauptthread hat die 9. Anweisungszeile ausgeführt, daher ist der Hauptthread der aktuelle Thread
public class MyThread extends Thread { @Override public void run() { super.run(); for (int i = ; i < ; i++) { System.out.println("i=" + (i + )); } } }
Sehen Sie sich das Beispiel der Methode isInterrupted() an:
public class Run { public static void main(String[] args) { try { MyThread thread = new MyThread(); thread.start(); Thread.sleep(); thread.interrupt(); //Thread.currentThread().interrupt(); System.out.println("是否停止?="+thread.interrupted());//false System.out.println("是否停止?="+thread.interrupted());//false main线程没有被中断!!! //......
In Zeile 8 handelt es sich um die Methode isInterrupted(), die vom Thread-Objekt aufgerufen wird. Daher wird der Unterbrechungsstatus des Threads getestet, der durch das Thread-Objekt dargestellt wird. Da in Zeile 7 der Hauptthread anfordert, den Thread-Thread zu unterbrechen, lautet das Ergebnis in Zeile 8: true
Weitere Artikel zum JAVA-Multithread-Unterbrechungsmechanismus stop(), interrupted(), isInterrupted() Bitte achten Sie auf die chinesische PHP-Website!