Pourquoi invoquer la méthode Thread.currentThread.interrupt()
dans le bloc catch?
Ceci est fait pour garder l'état .
Lorsque vous attrapez InterruptException
et que vous l'avalez, vous empêchez essentiellement les méthodes/groupes de threads de niveau supérieur de remarquer l'interruption. Ce qui peut causer des problèmes.
En appelant Thread.currentThread().interrupt()
, vous définissez le drapeau d'interruption du thread, afin que les gestionnaires d'interruptions de niveau supérieur le remarquent et puissent le gérer correctement.
La concurrence de Java en pratique en discute plus en détail dans 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. Le code de la tâche et de la bibliothèque à usage général ne doit jamais avaler les demandes d'interruption.
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 une interruption sans rétablir l'état.
Remarque:
Comment puis-je arrêter un thread qui attend de longues périodes (par exemple, une entrée)?
Pour que cette technique fonctionne, il est essentiel que toute méthode qui attrape une exception d'interruption et qui n'est pas prête à la gérer réitère immédiatement l'exception. Nous disons réaffirme plutôt que renvoyer, car il n'est pas toujours possible de renvoyer l'exception. Si la méthode qui intercepte l'InterruptedException n'est pas déclarée pour renvoyer cette exception (cochée), elle devrait alors "se réinterrompre" avec l'incantation suivante:
Thread.currentThread().interrupt();
Ceci garantit que le thread va relancer l'InterruptedException dès qu'il en sera capable.
Je considérerais cela comme une mauvaise pratique ou au moins un peu risqué. Habituellement, les méthodes de niveau supérieur n'effectuent pas d'opération de blocage et elles n'y verront jamais InterruptedException
. Si vous le masquez à chaque endroit où vous effectuez une opération interruptible, vous ne l'obtiendrez jamais.
La seule raison d'être de Thread.currentThread.interrupt()
et de ne pas déclencher une autre exception ou une demande d'interruption de signalisation d'une autre manière (par exemple, en définissant interrupted
une variable locale dans la boucle principale d'un thread) est le cas où vous pouvez réellement ne faites rien avec l'exception, comme dans les blocs finally
.
Voir la réponse de Péter Török si vous souhaitez mieux comprendre les implications de l'appel Thread.currentThread.interrupt()
.