Le mécanisme d'interruption du thread fournit une méthode pour réveiller un fil à partir d'une attente de blocage, essayant d'interrompre le flux de traitement existant du thread cible et de répondre aux nouvelles commandes. Java laisse cette liberté aux développeurs, et nous devons en faire bon usage.
Aujourd'hui, nous parlerons du mécanisme d'interruption des fils Java.
Le mécanisme d'interruption du thread fournit une méthode qui a deux utilisations courantes:
Réveillez le fil en attendant l'attente et effectuez un traitement correspondant «interruption contrôlé» correspondant.
Essayez d'informer le thread cible: veuillez interrompre le flux de traitement existant et répondre aux nouvelles commandes.
Prenez le premier objectif à titre d'exemple, veuillez consulter le code suivant:
synchronisé (lock) {try {while (! check ()) {lock.wait (1000); }} catch (InterruptedException e) {e.printStackTrace (); }}Ce code utilise le mécanisme d'attente / notification fourni par Java. L'exécution de threads de Lock.Wait () bloquera. Il y a trois situations pour restaurer le fil à exécuter.
1. Timeout 1000ms se termine et le code suivant est exécuté normalement.
2. Un autre thread exécute le code suivant pour se réveiller activement
synchronisé (lock) {lock.notifyall (); // ou lock.notify ();}Cela exécutera également le code suivant normalement.
3. Un autre fil qui doit attendre est "interrompre"
// Obtenez la référence au thread du thread d'attente a; a.interrupt ();
Le fil A qui est "interrompu" lancera une exception InterruptedException sur Lock.Wait ().
Pour résumer, vous pouvez penser que Object.Wait () fait ces choses en interne:
boolean checkTimeout = timeout> 0; thread current = thread.currentThread (); lock.addwaitter (current); while (! current.isnotified ()) {if (current.isinterrupted ()) {current.ClearInterrupted (); Jetez une nouvelle interruption (); } if (checkTimeout) {if (timeout == 0) Break; temps mort--; }}Ce n'est pas complètement exact, car Wait n'utilise pas cette méthode de "sondage occupé" pour vérifier, mais la logique de juger les bits de drapeau est correcte.
Commençons par l'opération "Interruption manuelle" mentionnée ci-dessus
// Sun.nio.ch.interrupblePublic Interface interruption {Void Interrupt (Thread var1);} // java.lang.threadprivate Blocker interruptible volatile; BlockerLock d'objet privé = nouveau objet (); public Void Interrupt () {if (this! = thread.currentThread ()) CheckAccess (); synchronisé (BlockerLock) {interruptible b = bloqueur; if (b! = null) {interrupt0 (); b.interrupt (ceci); retour; }} interrupt0 ();} // Juste pour définir l'interruption FlagPrivate native void interrupt0 ();On peut voir que thread.interrupt () juge d'abord les autorisations, puis appelle en fait Interrupt0 () pour définir l'indicateur d'interruption du thread. Si le thread actuel a l'interruption de Nio, il rappellera également.
Notez que Interrupt0 () définit simplement le drapeau d'interruption du fil.
Que se passe-t-il lorsqu'un thread ne bloque pas et n'est pas dans des zones qui ne sont pas contrôlées par la logique du programme Java, comme Object.Wait (), Thread.Join (), Thread.Sleep ()? La réponse est que rien ne se passera et si le fil est interrompu ne peut être connu qu'en vérifiant activement le drapeau d'interruption.
Comment vérifier? Le thread expose deux interfaces, Thread.Interrupted () et Thread.Isterrupted ().
// java.lang.threadpublic static boolean interrupted () {return currentThread (). isInterrupted (true);} public boolean isinterrupted () {return isterrupted (false);} private boolean isInterrupted (boolean clearterrupted);On peut voir que les deux reposent sur l'interruption interne (booléenne), qui renverra si le thread est interrompu et efface le drapeau d'interruption selon les besoins.
Lorsqu'un appel de fonction bloque, la fonction de la bibliothèque Java marque l'interruption de l'interruption dans la signature de la source de blocage et nécessite l'écriture d'essai pour gérer les interruptions.
Lorsque le thread bloque, comme mentionné ci-dessus, Java vérifie le drapeau d'interruption, l'efface d'abord, puis lance une interruption.
// java.lang.objectpublic final void wait () lève InterruptedException {wait (0);} public Final Native void wait (long timeout) lance InterruptedException;Si un thread reçoit une interruption de l'interruption et exécute ensuite le code qui lancera un blocage, il continuera de bloquer comme "peu importe". Parce que Java efface l'interruption en interne en interne!
Nous écrivons souvent les trois types de code suivants qui gèrent InterruptedException:
Gérez la conception interrompue vers la couche supérieure pour le traitement.
public void foo () lève InterruptedException {synchronisé (lock) {lock.wait (); }}InterruptedException réinitialise le bit du drapeau d'interruption.
essayez {synchronisé (lock) {lock.wait (); }} catch (InterruptedException e) {thread.currentThread (). Interrupt (); //casser; }Terminez d'abord votre travail, puis lancez à nouveau une interruption.
public void bar () lève InterruptedException {InterruptedException ie = null; booléen fait = false; while (! Done) {synchronisé (lock) {try {lock.wait (); } catch (InterruptedException e) {ie = e; continuer; }} fait = true; } if (ie! = null) {Throw IE; }}Si un thread ignore le drapeau d'interruption et InterruptedException, il fonctionne toujours bien. Mais cela est contraire à notre intention initiale de concevoir le multithreading. Nous voulons que les threads coopèrent harmonieusement et de manière ordonnée pour atteindre des fonctions spécifiques, les threads contrôlés doivent donc répondre aux interruptions. Et nous devons faire bon usage de cette liberté laissée par Java aux développeurs.
Ce qui précède est toutes les connaissances pertinentes sur le mécanisme d'interruption du thread Java qui vous est présenté cette fois. Si vous ne comprenez rien, vous pouvez en discuter dans la zone de message ci-dessous. Merci pour votre soutien à Wulin.com.