InterruptedException n'est peut-être pas aussi simple que vous le pensez !
Lorsque nous appelons la méthode wait() d'un objet Java ou la méthode sleep() d'un thread, nous devons intercepter et gérer l'exception InterruptedException. Si nous gérons incorrectement InterruptedException, des conséquences inattendues se produiront !
Par exemple, dans le code de programme suivant, la classe InterruptedTask implémente l'interface Runnable. Dans la méthode run(), le handle du thread actuel est obtenu, et dans la boucle while(true), le courant. le thread est détecté via la méthode isInterrupted(). Si le thread est interrompu, si le thread actuel est interrompu, quittez la boucle while(true). En même temps, dans la boucle while(true), il y a aussi une ligne de. Thread.sleep(100) et l’exception InterruptedException est capturée.
Le code complet est affiché ci-dessous.
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(); } } } }
L'intention initiale du code ci-dessus est de vérifier si le thread a été interrompu via la méthode isInterrupted() et de quitter la boucle while si elle est interrompue. D'autres threads interrompent le thread d'exécution en appelant la méthode interruption() du thread d'exécution. À ce moment, le bit d'indicateur d'interruption du thread d'exécution est défini, de sorte que currentThread.isInterrupted() renvoie true, afin que la boucle while puisse être. sorti.
Cela ne semble poser aucun problème ! Mais est-ce vraiment le cas ? Nous créons une classe InterruptedTest pour les tests, le code est le suivant.
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(); } }
Nous exécutons la méthode principale comme indiqué ci-dessous.
Le code ci-dessus appelle clairement la méthode interruption() du thread pour interrompre le thread, mais cela n'a aucun effet. La raison en est que lorsque la méthode run() du thread est exécutée, elle est bloquée la plupart du temps lors de sleep(100). Lorsque d'autres threads interrompent le thread d'exécution en appelant la méthode interruption() du thread d'exécution, InterruptedException sera déclenchée avec un. Forte probabilité. Exception, lorsque l'exception InterruptedException est déclenchée, la JVM effacera le bit d'indicateur d'interruption du thread en même temps, donc le currentThread.isInterrupted() jugé dans la méthode run() à ce moment retournera false, et la boucle while actuelle ne se terminera pas.
Maintenant que l'analyse du problème a été résolue, comment interrompre le fil de discussion et quitter le programme ?
La bonne façon de le résoudre devrait être d'intercepter l'exception dans la boucle while(true) de la méthode run() dans la classe InterruptedTask, puis de réinitialiser le bit de l'indicateur d'interruption, de sorte que le code correct de la classe InterruptedTask Comme indiqué ci-dessous.
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(); } } } }
Comme vous pouvez le voir, nous avons ajouté une nouvelle ligne de code dans le bloc de code catch qui capture l'exception InterruptedException.
currentThread.interrupt();
Cela nous permet de après avoir détecté l'exception InterruptedException, nous pouvons réinitialiser le bit d'indicateur d'interruption du thread, interrompant ainsi le thread en cours d'exécution.
Nous exécutons à nouveau la méthode principale de la classe InterruptedTest comme indiqué ci-dessous.
Soyez prudent lors de la gestion d'InterruptedException. Si une InterruptedException est levée lors de l'appel de la méthode interrompue () du thread d'exécution pour interrompre le thread d'exécution, alors lorsque l'exception InterruptedException est déclenchée, la JVM interrompra simultanément le thread d'exécution. Le bit de l'indicateur d'interruption est effacé à ce moment-là, lorsque la méthode isInterrupted() du thread d'exécution est appelée, false sera renvoyé.
À l'heure actuelle, la bonne façon de le gérer est d'intercepter l'exception InterruptedException dans la méthode run() du thread d'exécution et de réinitialiser le bit de l'indicateur d'interruption (c'est-à-dire dans le bloc de code catch qui intercepte l'exception InterruptedException, re -appelez la méthode interruption() du thread actuel.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!