English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Kurzanalyse des Interrupt-Mechanismus von Java-Threads

Der Thread-Unterbrechungsmechanismus bietet eine Methode, um den Thread aus dem blockierten Warten zu erwecken, versucht, den aktuellen Verarbeitungsprozess des Zielthreads zu unterbrechen und auf neue Befehle zu reagieren. Java gibt diesem Entwickler diese Freiheit, wir sollten sie gut nutzen.
Heute sprechen wir über das Unterbrechungsmechanismus der Java-Threads.

Das Thread-Unterbrechungsmechanismus bietet eine Methode, gibt es zwei häufige Verwendungen:

Wachen Sie den Thread aus dem blockierten Warten auf und führen Sie die entsprechende 'kontrollierte Unterbrechung' durch.
Versuchen Sie, dem Zielthread mitzuteilen: Unterbrechen Sie den aktuellen Verarbeitungsprozess und reagieren Sie auf neue Befehle.
Nehmen wir als Beispiel die erste Verwendung, siehe folgende Code:

synchronized (lock) {
  try {
    while (!check()) {
      lock.wait(1000);
    }
  }
    e.printStackTrace();
  }
}

Dieses Code verwendet wait bereitgestellt von Java/Das notify-Mechanismus, wenn der Thread lock.wait() ausführt, wird blockiert, gibt es drei Fälle, die den Thread wieder in Betrieb setzen.

1、Zeitüberschreitung 1000ms endet, normal ausführt das nächste Codezeile.

2、eine andere Thread führt das folgende Code aktiv aufwecken

synchronized (lock) {
  lock.notifyAll(); // oder lock.notify();
}

Dies wird normalerweise das nächste Codezeile ausführen.

3、eine andere Thread fordert den wartenden Thread '中断'

// Erhalten Sie den Verweis auf den wartenden Thread
Thread a;
a.interrupt();

Der Thread '中断' a wirft eine InterruptedException-Exception am lock.wait().

In summary, you can consider that object.wait() is doing these things internally:

boolean checkTimeout = timeout > 0;
Thread current = Thread.currentThread();
lock.addWaiter(current);
while (!current.isNotified()) {
  if (current.isInterrupted()) {
    current.clearInterrupted();
    throw new InterruptedException();
  }
  if (checkTimeout) {
    if (timeout == 0) break;
    timeout--;
  }
}

This is not entirely accurate because wait does not use this 'busy-wait' method for checking, but the logic for determining the flag is correct.

Let's start exploring the operation of 'manual interruption' mentioned above

// sun.nio.ch.Interruptible
public interface Interruptible {
  void interrupt(Thread var1);
}
// java.lang.Thread
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
public void interrupt() {
  if (this != Thread.currentThread())
    checkAccess();
  synchronized (blockerLock) {
    Interruptible b = blocker;
    if (b != null) {
      interrupt0();
      b.interrupt(this);
      return;
    }
  }
  interrupt0();
}
// Just to set the interrupt flag
private native void interrupt0();

It can be seen that thread.interrupt() first checks the permission, then actually calls interrupt0() to set the interrupt flag of the thread, and if the current thread has the nio's Interruptible, it will also call it back.

Please note that interrupt0() only sets the interrupt flag of the thread.

Wenn ein Thread nicht blockiert und sich nicht in Bereichen wie object.wait(), thread.join(), Thread.sleep() befindet, die nicht durch die Java-Programmlogik gesteuert werden, was geschieht dann? Die Antwort ist, dass nichts passiert, ob ein Thread unterbrochen wurde, kann nur durch aktives Überprüfen des Unterbrechungssignals ermittelt werden.

Wie überprüft man das? Thread stellt zwei Schnittstellen bereit, Thread.interrupted() und thread.isInterrupted().

// java.lang.Thread
public static boolean interrupted() {
  return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
  return isInterrupted(false);
}
private native boolean isInterrupted(boolean clearInterrupted);

Man kann erkennen, dass beide auf das interne isInterrupted(boolean) angewiesen sind, das zurückgibt, ob ein Thread unterbrochen wurde, und je nach Bedarf das Unterbrechungssignal löscht.

Wenn eine Funktion blockieren könnte, markiert die Java-Bibliotheksfunktion die Quelle der Blockierung mit throws InterruptedException und verlangt, try-catch zur Verarbeitung der Unterbrechung zu schreiben.

Wenn ein Thread blockiert, wie oben beschrieben, überprüft Java das Unterbrechungssignal und löscht es, bevor InterruptedException ausgelöst wird.

// java.lang.Object
public final void wait() throws InterruptedException {
  wait(0);
}
public final native void wait(long timeout) throws InterruptedException;

Wenn ein Thread InterruptedException erhält und trotzdem blockierenden Code ausführt, der zu einer Unterbrechung führen könnte, blockiert er wie ein 'Unbeteiligter'. Weil Java intern das Unterbrechungssignal gelöscht hat!

Wir schreiben in der Regel die folgenden drei Arten von Code, um InterruptedException zu behandeln:

InterruptedException wird an die Oberfläche weitergeleitet.

public void foo() throws InterruptedException {
  synchronized (lock) {
    lock.wait();
  }
}

Setzen Sie den Unterbrechungssignalindicator zurück, wenn InterruptedException auftritt.

try {
  synchronized (lock) { 
    lock.wait(); 
  } 
} 
  Thread.currentThread().interrupt();
  //break; 
}

Erledigen Sie zuerst die Arbeit und werfen Sie dann InterruptedException neu aus.

public void bar() throws InterruptedException {
  InterruptedException ie = null;
  boolean done = false;
  while (!done) {
    synchronized (lock) {
      try {
        lock.wait();
      }
        ie = e;
        continue;
      }
    }
    done = true;
  }
  if (ie != null) {
    throw ie;
  }
}

Wenn eine Thread die Unterbrechungssignale und InterruptedException ignoriert, kann er immer noch gut funktionieren. Dies ist jedoch im Widerspruch zu unserem ursprünglichen Ziel, Multi-Thread zu entwerfen. Wir möchten, dass die Threads harmonisch und geordnet zusammenarbeiten, um bestimmte Funktionen zu realisieren. Daher sollte ein kontrollierter Thread auf Unterbrechungen reagieren. Java gibt den Entwicklern diese Freiheit, und wir sollten sie gut nutzen.

Das war alles, was wir Ihnen heute über das Unterbrechungsmechanismus der Java-Threads erzählen konnten. Wenn Sie noch Fragen haben, können Sie im Kommentarbereich unten diskutieren. Vielen Dank für Ihre Unterstützung des呐喊教程.

Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet übernommen und gehört dem Urheberrechtsinhaber. Der Inhalt wurde von Internetnutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine rechtlichen Verantwortlichkeiten. Wenn Sie Inhalte finden, die möglicherweise urheberrechtlich geschützt sind, freuen wir uns über eine E-Mail an: notice#oldtoolbag.com (Bitte ersetzen Sie # durch @, wenn Sie eine Meldung senden, und fügen Sie relevante Beweise bei. Sobald nachgewiesen wird, dass Inhalte urheberrechtlich geschützt sind, wird diese Website die fraglichen Inhalte sofort löschen.)

Gefällt mir