84 votes

Qui appelle la méthode Java Thread interrupt() si ce n'est moi ?

J'ai lu et relu Java Concurrency in Practice, j'ai lu plusieurs fils de discussion ici sur le sujet, j'ai lu l'article d'IBM Traitement de l'InterruptedException et pourtant il y a quelque chose que je ne saisis tout simplement pas et qui, je pense, peut être décomposé en deux questions :

  1. Si je n'interromps jamais moi-même d'autres fils, qu'est-ce qui peut déclencher une InterruptedException ?

  2. Si je n'interromps jamais moi-même d'autres fils de discussion en utilisant interrompre() (disons parce que j'utilise d'autres moyens pour annuler mes fils de travail, comme les pilules empoisonnées et les while (!cancelled) (comme expliqué dans les deux cas dans le JCIP), que fait une InterruptedException Alors, ça veut dire ? Que suis-je censé faire si j'en attrape un ? Arrêter mon application ?

49voto

Stephen C Points 255558

Le mécanisme d'interruption de thread est le moyen privilégié pour qu'un thread (coopérant) réponde à une demande d'arrêt de son activité. Tout thread (y compris le thread lui-même, je pense) peut appeler interrupt() sur un fil.

En pratique, les cas d'utilisation normaux de interrupt() impliquent une sorte de cadre ou de gestionnaire qui demande à un fil de travail d'arrêter ce qu'il est en train de faire. Si le fil de travail est "conscient des interruptions", il remarquera qu'il a été interrompu par une exception ou en vérifiant périodiquement son drapeau d'interruption. Lorsqu'il s'aperçoit qu'il a été interrompu, un thread qui se comporte bien abandonne ce qu'il est en train de faire et se termine.

En supposant le cas d'utilisation ci-dessus, votre code est susceptible d'être interrompu s'il est exécuté dans un cadre Java ou à partir d'un fil de travail. Et lorsqu'il est interrompu, votre code doit abandonner ce qu'il est en train de faire et se terminer par le moyen le plus approprié. Selon la façon dont votre code a été appelé, cela peut se faire en retournant ou en lançant une exception appropriée. Mais il ne devrait probablement pas appeler System.exit() . (Votre application ne sait pas nécessairement pourquoi elle a été interrompue, et elle ne sait certainement pas s'il existe d'autres threads qui doivent être interrompus par le framework).

D'un autre côté, si votre code n'est pas conçu pour être exécuté sous le contrôle d'un framework, vous pourriez argumenter que l'option InterruptedException est une exception inattendue, c'est-à-dire un bogue. Dans ce cas, vous devez traiter l'exception comme vous le feriez pour d'autres bogues, c'est-à-dire l'envelopper dans une exception non vérifiée, l'attraper et l'enregistrer au même moment que vous traitez les autres exceptions non vérifiées inattendues. (Alternativement, votre application pourrait simplement ignorer l'interruption et continuer à faire ce qu'elle faisait).


UPDATE

Si je n'interromps jamais moi-même d'autres threads, qu'est-ce qui peut déclencher une InterruptedException ?

Par exemple, si votre Runnable sont exécutés à l'aide d'un ExecutorService y shutdownNow() est appelé sur le service. Et en théorie, n'importe quel pool de threads ou cadre de gestion de threads tiers pourrait légitimement faire quelque chose comme ça.

12voto

Brian Agnew Points 143181

Si vous décidez d'intégrer votre code à d'autres bibliothèques, celles-ci peuvent appeler interrupt() sur votre code. Par exemple, si vous décidez à l'avenir d'exécuter votre code dans le cadre d'une ExecutorService alors cela peut forcer un arrêt via interrupt() .

En bref, je ne me contenterais pas de considérer l'endroit où votre code est exécuté maintenant Par exemple, allez-vous le placer dans une bibliothèque ? Un conteneur ? Comment d'autres personnes l'utiliseront-elles ? Allez-vous le réutiliser ?

9voto

Comme d'autres l'ont souligné, l'interruption d'un thread (en fait, l'interruption d'un appel bloquant) est généralement utilisée dans le but de quitter proprement ou d'annuler une activité en cours.

Cependant, vous ne devez pas traiter un InterruptedException comme une "commande de sortie". Au lieu de cela, vous devriez considérer les interruptions comme un moyen de contrôler l'état d'exécution des threads, de la même manière que les commandes Object.notify() fait. De la même manière que vous vérifiez l'état actuel après avoir réveillé un appel à Object.wait() (vous ne supposez pas que le réveil signifie que votre condition d'attente a été satisfaite), après avoir reçu un coup de pouce avec une interruption, vous devez contrôler pourquoi vous avez été interrompu. Il existe généralement un moyen de le faire. Par exemple, java.util.concurrent.FutureTask a un isCancelled() méthode.

Exemple de code :

public void run() {
    ....
    try {
        .... // Calls that may block.
    } catch (InterruptedException e) {
        if (!running) {  // Add preferred synchronization here.
            return; // Explicit flag says we should stop running.
        }
        // We were interrupted, but the flag says we're still running.
        // It would be wrong to always exit here. The interrupt 'nudge'
        // could mean something completely different. For example, it
        // could be that the thread was blocking on a read from a particular
        // file, and now we should read from a different file.
        // Interrupt != quit (not necessarily).
    }
    ....
}
public void stop() {
    running = false; // Add preferred synchronization here.
    myThread.interrupt();
}

3voto

Le problème de la question est le "je". "Je" fait généralement référence à une seule instance d'une classe. Je veux dire par là qu'un morceau particulier de code de bas niveau (classe) ne doit pas dépendre de l'implémentation de l'ensemble du système. Cela dit, vous devez prendre certaines décisions "architecturales" (comme le choix de la plate-forme d'exécution).

Les éventuelles interruptions inattendues provenant du JRE sont des tâches annulées en java.util.concurrent et l'arrêt des applets.

La gestion des interruptions des threads est généralement mal écrite. Par conséquent, je suggère la décision architecturale d'éviter de provoquer des interruptions lorsque cela est possible. Cependant, le code qui gère les interruptions doit toujours être écrit correctement. On ne peut pas retirer les interruptions de la plate-forme maintenant.

0voto

Ash Points 5561

El InterruptedException dit qu'une routine mai être interrompue, mais pas nécessairement qu'elle le sera.

Si vous n'attendez pas l'interruption, vous devez la traiter comme toute autre exception inattendue. S'il s'agit d'une section critique où une exception inattendue pourrait avoir de terribles conséquences, il peut être préférable d'essayer de nettoyer les ressources et de s'arrêter de manière élégante (parce que l'interruption signale que votre application bien conçue qui ne dépend pas des interruptions est utilisée d'une manière qui n'a pas été prévue, et qu'il doit donc y avoir un problème). Sinon, si le code en question est quelque chose de non critique ou de trivial, vous pouvez ignorer (ou enregistrer) l'interruption et continuer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X