372 votes

Manutention InterruptedException en Java

Quelle est la différence entre l’une des manières suivantes de manutention `` ? Ce qui est le meilleur moyen de le faire.

OU

EDIT : je voudrais savoir aussi dans quels scénarios sont ces deux utilisé.

496voto

aioobe Points 158466

Mise à jour 2014-10-09: réécriture Complète de la réponse

Vous avez probablement venu de poser cette question parce que vous avez appelé une méthode qui jette InterruptedException.

Tout d'abord, vous devriez voir throws InterruptedException il est: Une partie de la signature de la méthode et les résultats possibles de l'appel de la méthode que vous appelez. Donc, commencer par embrasser le fait qu'un InterruptedException est parfaitement valide résultat de l'appel de méthode.

Maintenant, si la méthode que vous appelez jette une telle exception, ce qui devrait votre méthode? Vous pouvez trouver la réponse par la pensée sur les points suivants:

Est-il judicieux de la méthode , vous êtes à la mise en œuvre de jeter un InterruptedException? Pour le dire autrement, est une InterruptedException un bon résultat lors de l'appel de votre méthode?

  • Si oui, alors throws InterruptedException devrait être une partie de votre signature de la méthode, et vous devez laisser à l'exception propager (c'est à dire ne pas l'attraper).

    Exemple: Votre méthode attend pour une valeur de réseau pour terminer le calcul et renvoie un résultat. Si le blocage d'appel du réseau jette un InterruptedException votre méthode ne pouvez pas terminer le calcul d'une manière normale. Vous laissez l' InterruptedException propager.

    int computeSum(Server server) throws InterruptedException {
        // Any InterruptedException thrown below is propagated
        int a = server.getValueA();
        int b = server.getValueB();
        return a + b;
    }
    
  • Si pas, alors vous ne devez pas déclarer votre méthode avec des throws InterruptedException et vous doit (doivent!) intercepter l'exception. Maintenant, deux choses sont importantes à garder à l'esprit dans cette situation:

    1. Quelqu'un a interrompu votre fil. Que quelqu'un est probablement impatient pour annuler l'opération, terminer le programme normalement, ou quoi que ce soit. Vous devez être poli pour que quelqu'un et de retour de votre méthode sans plus tarder.

    2. Même si votre méthode peut gérer pour produire un bon de valeur de retour en cas d' InterruptedException le fait que le thread a été interrompu peut-être encore d'importance. En particulier, le code qui appelle votre méthode peut-être intéressé de savoir si une interruption s'est produite pendant l'exécution de votre méthode. Vous devez à cet effet le journal fait une interruption a eu lieu par le réglage de l'interruption de drapeau: Thread.currentThread().interrupt()

    Exemple: L'utilisateur a demandé d'imprimer une somme de deux valeurs. L'impression de "Failed to compute sum" est acceptable si la somme ne peut pas être calculée (et beaucoup mieux que de laisser le programme se ferme avec une trace de la pile en raison d'un InterruptedException). En d'autres termes, elle n'a pas de sens de les déclarer cette méthode avec throws InterruptedException.

    void printSum(Server server) {
         try {
             int sum = computeSum(server);
             System.out.println("Sum: " + sum);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();  // set interrupt flag
             System.out.println("Failed to compute sum");
         }
    }
    

Par maintenant, il devrait être clair que, tout en faisant throw new RuntimeException(e) est une mauvaise idée. Il n'est pas très poli de l'appelant. Soit quelqu'un a (A) soit une catch (RuntimeException e) qui va inclure, par exemple, NullPointerExceptions et comment sur la terre si une telle exception, être traitée correctement, ou (B) le programme va planter avec une RuntimeException trace de la pile.

D'autres exemples:

La mise en œuvre de Runnable: Comme vous l'avez peut-être découvert, la signature d' Runnable.run ne permet pas de renvoi InterruptedExceptions. Eh bien, vous avez signé sur la mise en œuvre de Runnable, ce qui signifie que vous avez signé pour faire face à d'éventuelles InterruptedExceptions. Choisir une interface différente, comme Callable, ou de suivre la deuxième approche ci-dessus.

 

Appelant Thread.sleep: Vous tentez de lire un fichier et de la spec dit que vous devriez essayer 10 fois avec 1 seconde entre les deux. Vous appelez Thread.sleep(1000). Donc, vous devez traiter avec des InterruptedException. Pour une méthode telle que l' tryToReadFile il est parfaitement logique de dire, "Si je suis interrompu, je ne peux pas terminer mon action de la tentative de lecture du fichier". En d'autres termes, il est parfaitement logique pour la méthode de jeter InterruptedExceptions.

String tryToReadFile(File f) throws InterruptedException {
    for (int i = 0; i < 10; i++) {
        if (f.exists())
            return readFile(f);
        Thread.sleep(1000);
    }
    return null;
}

111voto

mR_fr0g Points 3534

Il se trouve que je lisais sur ce sujet ce matin sur ma façon de travailler en Java de la Simultanéité Dans la Pratique par Brian Goetz. Fondamentalement, il est dit que vous devez effectuer l'une des deux choses

  1. Propager l' InterruptedException - Déclarer votre méthode de jeter les bagages InterruptedException de sorte que votre interlocuteur a à traiter avec elle.

  2. La restauration de l'Interruption - Parfois, vous ne pouvez pas jeter InterruptedException. Dans ces cas, vous devez attraper l' InterruptedException et de restauration de l'interruption, de par le statut de l'appel de la interrupt() méthode sur l' currentThread de sorte que le code plus haut dans la pile d'appel peut voir qu'une interruption a été émis.

25voto

Grodriguez Points 9945

Qu'essayez-vous de faire?

L' InterruptedException est levée lorsqu'un thread est en attente ou de couchage et un autre thread interruptions à l'aide de l' interrupt méthode dans la classe Thread. Donc, si vous attraper cette exception, il signifie que le thread a été interrompu. Habituellement, il n'ya pas de point dans les appelant Thread.currentThread().interrupt(); nouveau, sauf si vous souhaitez cochez la case "interrompu" le statut de l'filetage à partir de quelque part d'autre.

Concernant votre autre option que de jeter un RuntimeException, il ne semble pas une très bonne chose à faire (qui va attraper? comment seront-ils traités?) mais il est difficile d'en dire plus sans informations supplémentaires.

12voto

Nathan Hughes Points 30377

Pour moi, la clé, c'est: une InterruptedException n'est pas quelque chose va mal, c'est le thread de faire ce que vous lui avez dit de faire. Donc renvoi emballé dans une RuntimeException fait zéro sens.

Dans de nombreux cas, il est logique de renvoyer une exception enveloppé dans une RuntimeException quand vous dites, je ne sais pas ce qui s'est passé ici, et je ne peux rien faire pour le réparer, j'ai juste envie de sortir de la chaîne de traitement et de frapper quelle que soit l'échelle de l'application gestionnaire d'exception, que j'ai donc il peut se connecter. Ce n'est pas le cas avec une InterruptedException, c'est juste le fil de répondre pour avoir de l'interruption() a appelé, c'est jeter le InterruptedException afin de les aider à annuler le thread de traitement en temps opportun. Afin de propager la InterruptedException, ou de manger intelligemment (ce qui signifie à un endroit où il aura accompli ce qu'il devait faire) et de réinitialiser le drapeau d'interruption.

Voici une réponse que j'ai écrit décrivant comment les interruptions de travail, avec un exemple. Vous pouvez le voir dans l'exemple de code où il est à l'aide de la InterruptedException pour renflouer d'une boucle while dans le Praticable de la méthode run.

11voto

nedruod Points 750

Le bon choix par défaut, c'est d'ajouter InterruptedException à vos lancers liste. Une Interruption indique qu'un autre thread souhaite votre fil à la fin. La raison de cette demande n'est pas évident et est entièrement contextuelle, donc si vous n'avez pas de connaissances supplémentaires que vous devez supposer que c'est juste un match amical de l'arrêt, et tout ce qui évite que l'arrêt est une non-réponse favorable.

Java ne sera pas au hasard jeter InterruptedException, tous les conseils ne seront pas nuire à votre demande, mais j'ai couru dans un cas où le développeur est à la suite de la "avaler" la stratégie est devenu très gênant. Une équipe a développé un grand nombre de tests et de Fil utilisé.Dormir beaucoup. Maintenant qu'on a commencé à exécuter les tests dans notre serveur CI, et parfois, en raison de défauts dans le code serait coincé dans permanent attend. Pour aggraver la situation, lors de la tentative d'annuler l'IC de l'emploi il n'a jamais fermé parce que le Fil.Interruption qui a été destiné à interrompre le test n'a pas interrompre le travail. Nous avons eu de la connexion à la boîte manuellement et de tuer le processus.

Donc, c'est une longue histoire courte, si vous simplement jeter le InterruptedException vous êtes correspondant à la valeur par défaut de l'intention que votre fil fin. Si vous ne pouvez pas ajouter de InterruptedException à votre jet de liste, j'avais l'envelopper dans une RuntimeException.

Il est très rationnelle argument que InterruptedException devrait être une RuntimeException lui-même, parce que ce serait encourager une meilleure "par défaut" de la manipulation. Ce n'est pas une RuntimeException seulement parce que les concepteurs coincé à une catégorie de règle qu'une RuntimeException devrait représenter une erreur dans votre code. Depuis une InterruptedException ne se pose pas directement d'une erreur dans votre code, il ne l'est pas. Mais la réalité est que, souvent, une InterruptedException se pose car il y a une erreur dans votre code, (c'est à dire en boucle, dead-lock), et l'Interruption d'un autre thread méthode pour traiter l'erreur.

Si vous savez qu'il est rationnel de nettoyage à faire, puis le faire. Si vous connaissez une cause plus profonde de l'Interruption, vous pouvez prendre plus complète de la manipulation.

Donc en résumé votre choix pour le traitement devrait suivre cette liste:

  1. Par défaut, ajouter à jette.
  2. Si pas autorisé à ajouter à jette, jeter RuntimeException(e). (Meilleur choix de plusieurs mauvaises options)
  3. Seulement quand vous savez une cause explicite de l'Interruption, de la poignée comme souhaité. Si votre traitement est local à votre méthode, puis réinitialiser interrompue par un appel à enfiler.currentThread().interrupt().

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