Pourriez-vous expliquer ce que Java.lang.Thread.interrupt()
fait lorsqu'il est appelé?
Thread.interrupt()
définit le statut/drapeau interrompu du thread cible. Ensuite, le code s'exécutant dans ce thread cible PEUT interroger le statut interrompu et le gérer de manière appropriée. Certaines méthodes qui bloquent, telles que Object.wait()
, peuvent immédiatement utiliser l'état interrompu et générer une exception appropriée (généralement InterruptedException
)
Une interruption dans Java n’est pas préventive. En d'autres termes, les deux threads doivent coopérer afin de traiter correctement l'interruption. Si le thread cible n'interroge pas l'état interrompu, l'interruption est ignorée.
La scrutation a lieu via la méthode Thread.interrupted()
qui renvoie l’état interrompu du thread en cours ET annule cet indicateur d’interruption. Habituellement, le thread peut ensuite faire quelque chose comme lancer une exception InterruptedException.
EDIT (à partir des commentaires de Thilo): Certaines méthodes de l'API intègrent la gestion des interruptions. Du haut de ma tête cela inclut.
Object.wait()/Thread.sleep()
Java.util.concurrent
InterruptedException
, mais plutôt ClosedByInterruptException
.EDIT (de la réponse de @ thomas-pornin à exactement la même question pour compléter)
L'interruption du fil est une manière douce de pousser un fil. Il est utilisé pour donner aux threads une chance de sortir proprement , contrairement à Thread.stop()
qui ressemble plus à tirer sur le thread avec un fusil d'assaut.
Qu'est-ce qu'une interruption?
Une interruption est une indication pour un thread qu'il devrait arrêter ce qu'il est en train de faire et faire autre chose. C'est au programmeur de décider exactement comment un thread répond à une interruption, mais il est très courant que le thread se termine.
Comment est-il implémenté?
Le mécanisme d'interruption est mis en œuvre à l'aide d'un indicateur interne appelé statut d'interruption. L'appel de Thread.interrupt définit cet indicateur. Lorsqu'un thread recherche une interruption en appelant la méthode statique Thread.interrupted, l'état de l'interruption est effacé. Thread.isInterrupted non statique, utilisé par un thread pour interroger le statut d'interruption d'un autre, ne modifie pas l'indicateur de statut d'interruption.
Citation de Thread.interrupt()
API :
Interrompt ce fil. Tout d'abord, la méthode checkAccess de ce thread est appelée, ce qui peut provoquer la levée d'une exception SecurityException.
Si ce thread est bloqué lors d'un appel des méthodes wait (), wait (long) ou wait (long, int) de la classe Object ou de la méthode join (), join (long), join (long, int) , sleep (long), ou sleep (long, int), méthodes de cette classe, puis son statut d'interruption sera effacé et il recevra une exception InterruptedException.
Si ce thread est bloqué dans une opération d'E/S sur un canal interruptible, celui-ci sera fermé, l'état d'interruption du thread sera défini et le thread recevra une exception ClosedByInterruptException.
Si ce thread est bloqué dans un sélecteur, son statut d'interruption sera défini et il retournera immédiatement à partir de l'opération de sélection, éventuellement avec une valeur différente de zéro, comme si la méthode de réveil du sélecteur avait été appelée.
Si aucune des conditions précédentes n'est vérifiée, l'état d'interruption de ce thread sera défini.
Vérifiez ceci pour une compréhension complète à propos de la même chose:
http://download.Oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Si le thread ciblé a attendu (en appelant wait()
ou d'autres méthodes apparentées faisant essentiellement la même chose, tel que sleep()
), il sera interrompu, ce qui signifie qu'il n'attend plus ce qu'il est attendait et recevait une exception InterruptedException.
C'est au thread lui-même (le code qui s'appelle wait()
) de décider quoi faire dans cette situation. Cela ne met pas automatiquement fin au fil.
Il est parfois utilisé en combinaison avec un indicateur de terminaison. Lorsqu'il est interrompu, le thread pourrait vérifier cet indicateur, puis se fermer. Mais encore une fois, ceci est juste une convention.
Pour être complet, en plus des autres réponses, si le thread est interrompu avant qu'il ne se bloque sur Object.wait(..)
ou Thread.sleep(..)
etc., cela équivaut à son interruption immédiate lors du blocage sur cette méthode, comme le montre l'exemple suivant.
public class InterruptTest {
public static void main(String[] args) {
Thread.currentThread().interrupt();
printInterrupted(1);
Object o = new Object();
try {
synchronized (o) {
printInterrupted(2);
System.out.printf("A Time %d\n", System.currentTimeMillis());
o.wait(100);
System.out.printf("B Time %d\n", System.currentTimeMillis());
}
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("C Time %d\n", System.currentTimeMillis());
printInterrupted(3);
Thread.currentThread().interrupt();
printInterrupted(4);
try {
System.out.printf("D Time %d\n", System.currentTimeMillis());
Thread.sleep(100);
System.out.printf("E Time %d\n", System.currentTimeMillis());
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("F Time %d\n", System.currentTimeMillis());
printInterrupted(5);
try {
System.out.printf("G Time %d\n", System.currentTimeMillis());
Thread.sleep(100);
System.out.printf("H Time %d\n", System.currentTimeMillis());
} catch (InterruptedException ie) {
System.out.printf("WAS interrupted\n");
}
System.out.printf("I Time %d\n", System.currentTimeMillis());
}
static void printInterrupted(int n) {
System.out.printf("(%d) Am I interrupted? %s\n", n,
Thread.currentThread().isInterrupted() ? "Yes" : "No");
}
}
Sortie:
$ javac InterruptTest.Java
$ Java -classpath "." InterruptTest
(1) Am I interrupted? Yes
(2) Am I interrupted? Yes
A Time 1399207408543
WAS interrupted
C Time 1399207408543
(3) Am I interrupted? No
(4) Am I interrupted? Yes
D Time 1399207408544
WAS interrupted
F Time 1399207408544
(5) Am I interrupted? No
G Time 1399207408545
H Time 1399207408668
I Time 1399207408669
Implication: si vous bouclez comme suit et que l’interruption se produit au moment exact où le contrôle a quitté la fonction Thread.sleep(..)
et tourne autour de la boucle, l’exception se produira quand même. Il est donc parfaitement sûr de s’en remettre à l’exception de InterruptedException après l’interruption du thread:
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException ie) {
break;
}
}
Thread.interrupt()
définit l'état/le drapeau interrompu du thread cible sur true, ce qui, lorsqu'il est vérifié à l'aide de Thread.interrupted()
peut aider à arrêter le thread sans fin. Voir http://www.yegor256.com/2015/10/20/interrupted-exception.html
L'interruption du fil est basée sur le drapeau statut d'interruption. Pour chaque thread, la valeur par défaut de statut d'interruption est définie sur false. Chaque fois que la méthode interrupt () est appelée sur le thread, l'état d'interruption est défini sur true.
La méthode Thread.interrupt () active l'indicateur interne "statut de l'interruption". Généralement, cet indicateur est vérifié par la méthode Thread.interrupted ().
Par convention, toute méthode existant via InterruptedException doit effacer l'indicateur d'état d'interruption.
public void interruption ()
Interrompt ce fil.
Sauf si le thread en cours s'interrompt, ce qui est toujours autorisé, la méthode checkAccess de ce thread est invoquée, ce qui peut provoquer la levée d'une exception SecurityException.
Si ce thread est bloqué lors d'un appel des méthodes wait (), wait (long) ou wait (long, int) de la classe Object ou de la méthode join (), join (long), join (long, int) , sleep (long), ou sleep (long, int), méthodes de cette classe, puis son statut d'interruption sera effacé et il recevra une exception InterruptedException.
Si ce thread est bloqué dans une opération d'E/S sur un canal interruptible, celui-ci sera fermé, l'état d'interruption du thread sera défini et le thread recevra une exception ClosedByInterruptException.
Si ce thread est bloqué dans un sélecteur, son statut d'interruption sera défini et il retournera immédiatement à partir de l'opération de sélection, éventuellement avec une valeur différente de zéro, comme si la méthode de réveil du sélecteur avait été appelée.
Si aucune des conditions précédentes n'est vérifiée, l'état d'interruption de ce thread sera défini.
Interrompre un fil qui n'est pas en vie n'a pas d'effet.
Lance: SecurityException - si le thread actuel ne peut pas modifier ce thread
Une interruption est une indication pour un thread qu'il devrait arrêter ce qu'il est en train de faire et faire autre chose. C'est au programmeur de décider exactement comment un thread répond à une interruption, mais il est très courant que le thread se termine. Une très bonne référence: https://docs.Oracle.com/javase/tutorial/essential/concurrency/interrupt.html