Antworten:
Dies geschieht, um den Zustand zu erhalten .
Wenn Sie das fangen InterruptException
und es schlucken, verhindern Sie im Wesentlichen, dass übergeordnete Methoden / Thread-Gruppen den Interrupt bemerken. Was zu Problemen führen kann.
Durch Aufrufen setzen Thread.currentThread().interrupt()
Sie das Interrupt-Flag des Threads, damit Interrupt-Handler höherer Ebenen es bemerken und es entsprechend behandeln können.
Java Concurrency in Practice beschreibt dies ausführlicher in Kapitel 7.1.3: Reagieren auf Unterbrechungen . Ihre Regel lautet:
Nur Code, der die Unterbrechungsrichtlinie eines Threads implementiert, kann eine Unterbrechungsanforderung verschlucken. Allzweck-Task und Bibliothekscode sollten niemals Unterbrechungsanforderungen verschlucken.
interrupt()
Anruf ist der einzige Weg setzen die unterbrochene Flag , wenn Sie Benachrichtigung über diesen Zustand durch den anderen „Liefermechanismus“ erhalten - das InterruptedException
wünscht oder nicht , es erneut zu werfen.
Ich denke, dieses Codebeispiel macht die Dinge ein bisschen klar. Die Klasse, die den Job macht:
public class InterruptedSleepingThread extends Thread {
@Override
public void run() {
doAPseudoHeavyWeightJob();
}
private void doAPseudoHeavyWeightJob() {
for (int i=0;i<Integer.MAX_VALUE;i++) {
//You are kidding me
System.out.println(i + " " + i*2);
//Let me sleep <evil grin>
if(Thread.currentThread().isInterrupted()) {
System.out.println("Thread interrupted\n Exiting...");
break;
}else {
sleepBabySleep();
}
}
}
/**
*
*/
protected void sleepBabySleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
//e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
Die Hauptklasse:
public class InterruptedSleepingThreadMain {
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
InterruptedSleepingThread thread = new InterruptedSleepingThread();
thread.start();
//Giving 10 seconds to finish the job.
Thread.sleep(10000);
//Let me interrupt
thread.interrupt();
}
}
Versuchen Sie, Interrupt aufzurufen, ohne den Status zurückzusetzen.
Hinweis:
Wie stoppe ich einen Thread, der lange wartet (z. B. auf Eingabe)?
Damit diese Technik funktioniert, ist es wichtig, dass jede Methode, die eine Interrupt-Ausnahme abfängt und nicht bereit ist, damit umzugehen, die Ausnahme sofort erneut bestätigt. Wir sagen eher erneutes Setzen als erneutes Werfen, da es nicht immer möglich ist, die Ausnahme erneut zu werfen. Wenn die Methode, die die InterruptedException abfängt, nicht deklariert ist, um diese (aktivierte) Ausnahme auszulösen, sollte sie sich mit der folgenden Beschwörung "erneut unterbrechen":
Thread.currentThread().interrupt();
Dadurch wird sichergestellt, dass der Thread die InterruptedException erneut aktiviert, sobald dies möglich ist.
Ich würde es als schlechte Praxis oder zumindest ein bisschen riskant betrachten. Normalerweise führen übergeordnete Methoden keine Blockierungsvorgänge aus und werden dort nie angezeigt InterruptedException
. Wenn Sie es an jedem Ort maskieren, an dem Sie einen unterbrechbaren Betrieb ausführen, werden Sie es nie bekommen.
Der einzige Grund dafür Thread.currentThread.interrupt()
, dass keine andere Ausnahme oder Signalisierungsunterbrechungsanforderung auf andere Weise ausgelöst wird (z. B. Festlegen einer interrupted
lokalen Variablenvariablen in der Hauptschleife eines Threads), ist die Situation, in der Sie mit der Ausnahme wirklich nichts tun können, wie in den finally
Blöcken.
Sehen Sie sich die Antwort von Péter Török an, wenn Sie die Auswirkungen des Thread.currentThread.interrupt()
Anrufs besser verstehen möchten .
Siehe Java-Dokument
Wenn dieser Thread bei einem Aufruf von wait (), join (), sleep (long) blockiert wird, wird sein Interrupt-Status gelöscht und eine InterruptedException empfangen.
Wenn dieser Thread in einer E / A-Operation blockiert wird, wird der Interrupt-Status des Threads festgelegt und der Thread erhält eine ClosedByInterruptException.
Wenn dieser Thread in einem Selector blockiert ist, wird der Interrupt-Status des Threads gesetzt und er kehrt sofort von der Auswahloperation zurück.
Wenn keine der vorherigen Bedingungen erfüllt ist, wird der Interrupt-Status dieses Threads festgelegt.
Wenn Sie also die sleepBabySleep () -Methode in @Ajay George Answer to I / O-Operation oder nur ein Sysout ändern, müssen Sie den Status nicht zurücksetzen, um das Programm zu stoppen. (Übrigens werfen sie nicht einmal InterruptedException)
Genau wie @ Péter Török sagte => Dies geschieht, um den Zustand zu erhalten. (Und insbesondere für Methoden, die InterruptedException auslösen)
InterruptedException
löscht jede Methode, die durch Auslösen eines Interrupt-Status beendet wird, dies. Ich denke, dies macht die Antwort klarer, warum Sie den Interrupt-Status beibehalten müssen.