« Bonjour, Amigo ! Il faut reconnaître qu'Ellie a eu une brillante idée avec Cancel. »

« Ouaip. »

« Mais vois-tu, il existe quelque chose de semblable dans la classe Thread. Sauf que la variable ne s'appelle pas isCancel. Elle s'appelle isInterrupted. Et la méthode utilisée pour arrêter le thread n'est pas cancel(). C'est interrupt(). »

« C'est vrai ? »

« Oui. Regarde un peu : »

Code Description
class Clock implements Runnable
{
public void run()
{
Thread current = Thread.currentThread();

while (!current.isInterrupted())
{
Thread.sleep(1000);
System.out.println("Tick");
}
}
}
Comme plusieurs threads peuvent appeler la méthode run sur le même objet Clock, nous récupérons l'objet Thread pour le thread en cours.

La classe Clock écrit le mot 'Tic' dans la console une fois par seconde tant que la variable isInterrupted du thread actuel a la valeur false.

Quand isInterrupted passe à true, la méthode run se termine.

public static void main(String[] args)
{
Clock clock = new Clock();
Thread clockThread = new Thread(clock);
clockThread.start();

Thread.sleep(10000);
clockThread.interrupt();
}
Le thread principal démarre un thread enfant (l'horloge) qui doit s'exécuter indéfiniment.

Attends 10 secondes et  annule la tâche en appelant la méthode interrupt.

Le thread principal termine son travail.

Le thread d'horloge termine son travail.

Par ailleurs, la méthode sleep, que les gens adorent tant utiliser dans des boucles sans fin dans la méthode run, vérifie automatiquement la variable isInterrupted. Si un thread appelle la méthode sleep, la méthode vérifie d'abord si isInterrupted a la valeur true pour ce thread. Si c'est le cas, la méthode n'attend pas. Au lieu de cela, elle lève une exception InterruptedException.

« Pourquoi lever une exception ? Ce ne serait pas mieux de simplement mettre isInterrupted() au lieu de isCancel() dans une boucle ? »

« Pour commencer, la méthode run n'a pas toujours une boucle. La méthode pourrait simplement consister en quelques dizaines d'appels à d'autres méthodes. Dans ce cas, tu devrais vérifier isInterrupted avant chaque appel de méthode. »

« Deuxièmement, une méthode qui implique beaucoup d'actions différentes peut prendre un temps très long pour s'exécuter. »

« Troisièmement, lever une exception ne remplace pas la vérification d'isInterrupted. C'est juste un ajout pratique. L'exception levée te permet de rapidement dérouler la pile d'appels jusqu'à la méthode run elle-même. »

« Quatrièmement, la méthode sleep est très fréquemment utilisée. Il se trouve que cette méthode utile est renforcée par un contrôle implicite qui n'est pas moins utile. C'est comme si personne n'ajoutait spécifiquement la vérification, mais qu'elle était là. C'est extrêmement utile lorsque tu utilises le code de quelqu'un d'autre et que tu ne peux pas ajouter la vérification toi-même. »

« Cinquièmement, la vérification supplémentaire ne dégrade pas les performances. Appeler la méthode sleep signifie que le thread ne doit rien faire (sauf attendre), afin que le travail supplémentaire ne dérange personne. »

« Ce sont de sérieux arguments. »

« Et enfin, il y a ceci : Ta méthode run peut appeler le code de quelqu'un d'autre, un code auquel tu n'as pas accès (tu n'as pas le code source et/ou le droit de modifier le code). Il pourrait ne pas avoir des vérifications d'isInterrupted, et utiliser 'try ... catch (Exception e)' pour capturer toutes les exceptions. »

Personne ne peut garantir qu'un thread sera arrêté. Seul un thread peut s'arrêter lui-même.