Réponses:
Ceci est fait pour garder l'état .
Lorsque vous attrapez le InterruptException
et l'avalez, vous empêchez essentiellement les méthodes / groupes de threads de niveau supérieur de remarquer l'interruption. Ce qui peut poser des problèmes.
En appelant Thread.currentThread().interrupt()
, vous définissez l'indicateur d'interruption du thread, de sorte que les gestionnaires d'interruptions de niveau supérieur le remarqueront et pourront le gérer de manière appropriée.
Java Concurrency in Practice aborde ce sujet plus en détail au Chapitre 7.1.3: Répondre à une interruption . Sa règle est:
Seul le code qui implémente la politique d'interruption d'un thread peut avaler une demande d'interruption. Les tâches générales et le code de bibliothèque ne doivent jamais avaler les demandes d'interruption.
interrupt()
appel est le seul moyen de définir l'indicateur d'interruption une fois que vous avez reçu une notification concernant cet état via l'autre «mécanisme de livraison» - le InterruptedException
et que vous souhaitez ou ne pouvez pas le relancer.
Je pense que cet exemple de code rend les choses un peu claires. La classe qui fait le travail:
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();
}
}
}
La classe principale:
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();
}
}
Essayez d'appeler l'interruption sans rétablir l'état.
Remarque:
Comment arrêter un thread qui attend pendant de longues périodes (par exemple, pour une entrée)?
Pour que cette technique fonctionne, il est essentiel que toute méthode qui intercepte une exception d'interruption et n'est pas prête à la traiter réaffirme immédiatement l'exception. Nous disons réaffirmer plutôt que renvoyer, car il n'est pas toujours possible de renvoyer l'exception. Si la méthode qui intercepte l'exception InterruptedException n'est pas déclarée pour lever cette exception (vérifiée), alors elle doit "se réinterrompre" avec l'incantation suivante:
Thread.currentThread().interrupt();
Cela garantit que le thread relèvera l'exception InterruptedException dès qu'il le pourra.
Je considérerais cela comme une mauvaise pratique ou au moins un peu risquée. Habituellement, les méthodes de niveau supérieur n'effectuent pas d'opérations de blocage et elles ne verront jamaisInterruptedException
. Si vous le masquez à chaque endroit où vous effectuez une opération interruptible, vous ne l'obtiendrez jamais.
La seule justification pour Thread.currentThread.interrupt()
et ne pas déclencher une autre exception ou une demande d'interruption de signalisation d'une autre manière (par exemple, définir interrupted
une variable de variable locale dans la boucle principale d'un thread) est la situation où vous ne pouvez vraiment rien faire avec l'exception, comme dans les finally
blocs.
Voir la réponse de Péter Török, si vous voulez mieux comprendre les implications de l' Thread.currentThread.interrupt()
appel.
Se référer à la documentation java
Si ce thread est bloqué lors d'un appel de wait (), join (), sleep (long), son état d'interruption sera effacé et il recevra une InterruptedException.
Si ce thread est bloqué dans une opération d'E / S, l'état d'interruption du thread sera défini et le thread recevra une ClosedByInterruptException.
Si ce thread est bloqué dans un sélecteur, l'état d'interruption du thread sera défini et il reviendra immédiatement après l'opération de sélection.
Si aucune des conditions précédentes ne tient, l'état d'interruption de ce thread sera défini.
Donc, si vous changez la méthode sleepBabySleep () dans @Ajay George Answer to I / O operation ou juste un sysout, vous n'avez pas à redéfinir le statut pour arrêter le programme. (BTW, ils ne lancent même pas InterruptedException)
Tout comme @ Péter Török a dit => Ceci est fait pour garder l'état. (Et en particulier pour la méthode qui lancera InterruptedException)
InterruptedException
statut d'interruption efface quand elle le fait. Je pense que cela rend la réponse plus claire en termes de pourquoi vous devez conserver l'état d'interruption.