Que fait java.lang.Thread.interrupt ()?

Réponses:

251

Thread.interrupt()définit l'état / l'indicateur interrompu du thread cible. Ensuite, le code exécuté dans ce thread cible PEUT interroger l'état interrompu et le gérer de manière appropriée. Certaines méthodes qui bloquent, par exemple, Object.wait()peuvent consommer immédiatement l'état interrompu et lever une exception appropriée (généralement InterruptedException)

L'interruption en Java n'est pas préventive. Autrement dit, 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 effectivement ignorée.

L'interrogation se produit via la Thread.interrupted()méthode qui renvoie l'état interrompu du thread actuel ET efface cet indicateur d'interruption. Habituellement, le thread peut alors faire quelque chose comme lever InterruptedException.

EDIT (d'après les commentaires de Thilo): Certaines méthodes API ont intégré la gestion des interruptions. Du haut de ma tête, cela comprend.

  • Object.wait(),, Thread.sleep()etThread.join()
  • La plupart des java.util.concurrentstructures
  • Java NIO (mais pas java.io) et il n'utilise PAS InterruptedException, à la place ClosedByInterruptException.

EDIT (de la réponse de @ thomas-pornin à exactement la même question pour être complet)

L'interruption du fil est un moyen doux de pousser un fil. Il est utilisé pour donner aux fils une chance de sortir proprement , par opposition à Thread.stop()cela, c'est plus comme tirer sur le fil avec un fusil d'assaut.

Mike Q
la source
22
Notez que des méthodes telles que sleep ou wait effectuent ce type d'interrogation et lèvent InterruptedException par elles-mêmes.
Thilo
1
Si vous utilisez des E / S de fichiers interruptibles, l'effet ne sera pas si doux. Vous obtiendrez généralement la corruption de fichiers.
Marko Topolnik
si vous mentionnez Thread.interrupted, il semble qu'il convient de mentionner qu'il existe également un indicateur Thread.isInterrupted, qui n'efface pas l'indicateur, ce qui le rend généralement plus approprié pour une utilisation par les développeurs d'applications.
Nathan Hughes
67

Qu'est-ce que l'interruption?

Une interruption est une indication pour un thread qu'il doit arrêter ce qu'il fait 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 mis en œuvre?

Le mécanisme d'interruption est implémenté à l'aide d'un indicateur interne appelé état d'interruption. L'appel de Thread.interrupt définit ce drapeau. Lorsqu'un thread recherche une interruption en appelant la méthode statique Thread.interrupted, l'état d'interruption est effacé. Le Thread.isInterrupted non statique, qui est utilisé par un thread pour interroger l'état d'interruption d'un autre, ne modifie pas l'indicateur d'état d'interruption.

Citation de l' Thread.interrupt()API :

Interrompt ce fil. Tout d'abord, la méthode checkAccess de ce thread est invoquée, ce qui peut provoquer la levée d'une SecurityException.

Si ce thread est bloqué lors d'une invocation des méthodes wait (), wait (long) ou wait (long, int) de la classe Object, ou des fonctions join (), join (long), join (long, int) , sleep (long) ou sleep (long, int), les méthodes de cette classe, puis son état d'interruption sera effacé et il recevra une InterruptedException.

Si ce thread est bloqué dans une opération d'E / S sur un canal interruptible, le canal 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, l'état d'interruption du thread sera défini et il reviendra immédiatement de l'opération de sélection, éventuellement avec une valeur non nulle, comme si la méthode de réveil du sélecteur était invoquée.

Si aucune des conditions précédentes n'est remplie, l'état d'interruption de ce thread sera défini.

Vérifiez ceci pour une compréhension complète à ce sujet:

http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html

YoK
la source
C'est obéir à une explication partielle. Il interrompt également les méthodes interruptibles.
Marquis de Lorne
@EJP Cette question porte sur la méthode Thread.interrupt () et son fonctionnement. Je pense que tout ce que j'ai publié avec un lien, répond à ce qui est demandé. Je ne comprends toujours pas ce que tu souhaites?
YoK
Je souhaite que vous corrigiez votre déclaration partiellement incorrecte selon laquelle elle est mise en œuvre par un indicateur. Ce n'est qu'une partie de l'histoire. Cela me semble assez clair.
Marquis de Lorne
@EJP Merci. Maintenant, je comprends ce que vous disiez. J'ai mis à jour ma réponse et ajouté un document API pour la méthode. Cela couvre la partie des méthodes interruptibles qui manquait à ma réponse. J'espère que ma réponse semble complète maintenant :).
YoK
13

Si le thread ciblé a attendu (en appelant wait(), ou d'autres méthodes connexes qui font essentiellement la même chose, comme sleep()), il sera interrompu, ce qui signifie qu'il cesse d'attendre ce qu'il attendait et reçoit une exception InterruptedException à la place.

C'est entièrement au thread lui-même (le code qui l'a appelé wait()) de décider quoi faire dans cette situation. Il ne termine pas automatiquement le thread.

Il est parfois utilisé en combinaison avec un indicateur de terminaison. Lorsqu'il est interrompu, le thread peut vérifier cet indicateur, puis s'arrêter. Mais encore une fois, ce n'est qu'une convention.

Thilo
la source
9 ans, réponse sans âge! +1
snr
10

Pour être complet, en plus des autres réponses, si le thread est interrompu avant de se bloquer sur Object.wait(..)ou Thread.sleep(..)etc., cela équivaut à être interrompu immédiatement 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");
    }
}

Production:

$ 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 est parti Thread.sleep(..)et fait le tour de la boucle, l'exception va toujours se produire. Il est donc parfaitement sûr de se fier à InterruptedException de façon fiable après que le thread a été interrompu :

while (true) {
    try {
        Thread.sleep(10);
    } catch (InterruptedException ie) {
        break;
    }
}
Evgeni Sergeev
la source
4

L'interruption de thread est basée sur l' état d'interruption de l' indicateur . Pour chaque thread, la valeur par défaut du statut d'interruption est définie sur false . Chaque fois que la méthode interrupt () est appelée sur le thread, le statut d'interruption est défini sur true .

  1. Si interruption status = true (interrupt () déjà appelé sur le thread), ce thread particulier ne peut pas se mettre en veille. Si sleep est appelé sur ce thread, une exception interrompue est levée. Après avoir lancé une nouvelle exception, le drapeau est défini sur false.
  2. Si le thread est déjà en sommeil et que l' interruption () est appelée, le thread sortira de l'état de sommeil et lèvera une exception interrompue.
akash G
la source
1

interruption de vide public ()

Interrompt ce fil.

À moins que le thread actuel ne 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 SecurityException.

Si ce thread est bloqué lors d'une invocation des méthodes wait (), wait (long) ou wait (long, int) de la classe Object, ou des fonctions join (), join (long), join (long, int) , sleep (long) ou sleep (long, int), les méthodes de cette classe, puis son état d'interruption sera effacé et il recevra une InterruptedException.

Si ce thread est bloqué dans une opération d'E / S sur un canal interruptible, le canal 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, l'état d'interruption du thread sera défini et il reviendra immédiatement de l'opération de sélection, éventuellement avec une valeur non nulle, comme si la méthode de réveil du sélecteur était invoquée.

Si aucune des conditions précédentes n'est remplie, l'état d'interruption de ce thread sera défini.

L'interruption d'un thread qui n'est pas vivant n'a aucun effet.

Génère: SecurityException - si le thread actuel ne peut pas modifier ce thread

Ajeet Ganga
la source
1

La méthode Thread.interrupt () définit l'indicateur interne «statut d'interruption». Habituellement, cet indicateur est vérifié par la méthode Thread.interrupted ().

Par convention, toute méthode qui existe via InterruptedException doit effacer l'indicateur d'état d'interruption.

Anatoliy Shuba
la source