Est-il correct d’ignorer InterruptedException si personne n’appelle interruption ()?

Si je crée mon propre thread (c’est-à-dire pas un threadpool) et quelque part j’appelle sleep ou toute autre méthode interruptible, est-il correct d’ignorer l’InterruptedException si je sais que personne d’autre dans le code ne fait une interruption sur le thread .

En d’autres termes, si le thread est supposé vivre aussi longtemps que la JVM, ce qui signifie que le thread n’est pas interruptible, est-il sûr de supposer qu’InterruptedException ne sera jamais appelée et que par conséquent, l’exception peut être avalée?

    Ignorer une exception vérifiée n’est jamais considérée comme sûre.
    Cela peut vous convenir pour le moment, mais si un autre programmeur étend votre code, il attendra le comportement standard: le thread réagissant à un appel d’interruption.
    De plus, un bloc de capture vide est dangereux dans ce cas, car la JVM supprime le drapeau interrompu et il devrait définitivement être remis à

     Thread.currentThread().interrupt(); 

    dans le bloc de capture. À mon avis, il s’agit de l’implémentation minimale de capture pour InterruptedException s. Vérifier l’indicateur isInterrupted dans une boucle ne fait pas mal non plus.
    Ce n’est pas une mince affaire par rapport à la recherche de votre futur programmeur en cherchant un jour ou deux pour un comportement inattendu des threads car votre projet a peut-être augmenté un peu.

    Si vous pensez que la lisibilité de votre code est affectée par ces implémentations, vous pouvez implémenter votre propre méthode utilitaire safeSleep , qui safeSleep les Exception et positionne correctement l’indicateur.

    En revanche, InterruptedException n’est pas renvoyé par la JVM en cas de défaillance matérielle, il s’agit uniquement d’une Exception indiquée par l’utilisateur . Ainsi, si vous ne Thread.interrupt() pas la référence de votre Thread , aucun autre Thread ne pourra appeler Thread.interrupt() dessus. C’est ça techniquement . Mais vous ne devez pas sous-estimer le facteur humain et l’évolution de vos programmes.
    Edit: Comme ruakh l’a fait remarquer, il existe un moyen d’obtenir une référence à Thread et donc de planifier un appel à Thread.interrupt() . De cette façon, le développeur en chaleur n’aura peut-être même pas à regarder la classe qui implémente votre Thread ininterruptible. À mon avis, c’est même une autre raison pour mettre en œuvre une gestion correcte des exceptions.
    Autre chose : si vous ne lancez pas d’ Exception , vous pouvez choisir de vous connecter à un niveau au-delà d’ INFO .

    Au lieu de l’avaler, si vous êtes tellement sûr que cela n’arrivera jamais, vous pouvez vous écraser au lieu de l’ignorer. Par exemple, lancez une Error (ou une RuntimeException ):

     try { Thread.sleep(1000); } catch (InterruptedException e) { throw new Error(e); } 

    Depuis Javadocs pour Error :

    Une erreur est une sous-classe de Throwable qui indique des problèmes graves qu’une application raisonnable ne devrait pas tenter de résoudre. La plupart de ces erreurs sont des conditions anormales.

    Si vous pensez que cela vaut la peine de supposer que quelque chose n’arrivera jamais, alors si c’est le cas, il s’agit d’une “condition anormale” qui, qui sait, pourrait bien être un “problème grave”.

    Une autre façon de voir cela est que si quelqu’un interrompt votre méthode dans le futur, y a-t-il une chance pour qu’il continue à fonctionner comme si de rien n’était? Je suppose que non.

    Vous ne devriez jamais avaler une exception si vous pensez que cela ne devrait jamais se produire. Il est acceptable de ne pas append de code pour gérer une condition qui ne se produit jamais mais cela ne devrait pas se produire en silence .

    Le minimum à faire est de:

     catch(InterruptedException ex) { throw new AssertionError(ex); } 

    Cela garantit que chaque fois que votre affirmation que cela ne se produira jamais est fausse, vous le remarquerez. Ce modèle s’applique également à d’autres exceptions inattendues, par exemple IOException lorsque vous savez que la cible OutputStream est un object ByteArrayOutputStream ou que l’ Appendable d’un Formatter doit être un object SsortingngBuilder , etc.


    Par ailleurs, il existe une alternative à Thread.sleep ne nécessitant pas du tout d’ InterruptedException :

     LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(timeInMillis)); 

    Cette méthode retournera simplement plus tôt lorsque le thread aura été interrompu et conservera l’état interrompu du Thread ce qui fournit déjà une gestion correcte du cas où votre code est utilisé par une autre personne qui utilise une interruption (en supposant que l’appelant de votre code vérifie alors l’état interrompu).

    Le livre que je considère toujours comme la bible sur ces questions, Goetz et al. La concurrence dans la pratique Java dit les éléments importants suivants dans le chapitre 7 (à peu près le même matériau se trouve dans l’ article developerWorks de Goetz, qui a l’avantage d’être gratuit, mais le livre est un peu plus clair sur certains points).

    L’interruption est un mécanisme de coopération. Un thread ne peut pas forcer un autre à arrêter ce qu’il fait et à faire autre chose; Lorsque le thread A interrompt le thread B, A demande simplement que B arrête ce qu’il fait lorsqu’il arrive à un point d’arrêt approprié, si cela lui semble.

    […]

    Seul le code qui implémente la politique d’interruption d’un thread peut avaler une demande d’interruption. Les tâches et le code de bibliothèque à usage général ne doivent jamais avaler les demandes d’interruption.

    Donc, oui, vous pouvez “avaler” InterruptedException dans les circonstances que vous avez décrites.

    Aussi un point important dans le livre:

    Comme chaque thread a sa propre politique d’interruption, vous ne devez pas interrompre un thread à moins que vous ne sachiez ce que signifie l’interruption pour ce thread.

    Vous pouvez donc choisir votre propre stratégie comme ” RuntimeException ” avec une RuntimeException , AssertionError , simplement la connecter en tant RuntimeException ou ignorer l’interruption tant que vous documentez ce problème pour quiconque pourrait avoir besoin de le savoir. Le meilleur dépend de ce que votre sujet fait réellement et vous n’avez fourni aucun détail à ce sujet. Par exemple, si ça tourne sur une fusée [disons faire le contrôle d’attitude], vous ne voulez pas planter la JVM / Rocket juste parce qu’un autre programmeur [qui ne travaillera peut-être même pas pour vous call] a oublié un contrat quelque part dans son code et supprime sur le vôtre une exception qui ne peut être ignorée: “L’exception qui s’est produite n’était pas due à une défaillance aléatoire, mais à une erreur de conception.”

    Si votre Projekt se développe et devient plus complexe, il devient plus difficile de dire que personne n’appellera la méthode d’interruption. Si quelqu’un appelle cette méthode un jour et qu’une exception InterruptedException se produit, il devient vraiment difficile de déboguer cette méthode si vous ne la connectez pas au moins quelque part.

    Cela ne devrait pas être ignoré. Il doit être renvoyé à l’appelant ou vous devez réaffirmer le statut interrompu du thread qui est effacé lorsque l’exception est levée:

     catch (InterruptedException e) { // Restore the interrupted status Thread.currentThread().interrupt(); } 

    sauf si vous quittez rapidement le fil après le rattrapage.

    Voici un article sur le traitement des InterruptedException s.

    si le thread est censé vivre aussi longtemps que la machine virtuelle Java, ce qui signifie que le thread n’est pas interruptible, est-il prudent de supposer InterruptedException ne sera jamais levée et que l’exception peut donc être avalée?

    Je comprends votre douleur, la prolifération de blocs d’essai classiques sans valeur commerciale nuit au code.

    Si le code où vous avez l’intention d’avaler l’exception est entièrement sous votre contrôle, et s’il ne s’agit que du code client (il ne sera jamais réutilisé dans un contexte autre que le vôtre), vous pouvez alors avaler l’exception en toute sécurité. Notez qu’il y a beaucoup de si s là.

    Si vous travaillez avec Java 8, vous avez une autre option, décrite ici : envelopper votre code dans un uncheckCall(() -> { ... }) . Cela permet au bloc de code de lancer l’ InterruptedException sans la déclarer. Comme expliqué dans la réponse liée, ceci doit être traité avec une extrême prudence, mais cela peut potentiellement rendre votre code très propre.

    Je pense, ignorer InterruptedException est sûr ou non, dépend de ce que vous faites dans ce thread. S’il existe un scénario dans lequel une interruption indésirable de votre thread peut laisser le système ou une ressource dans un état indésirable (sale, verrouillé, non libéré, ce qui peut entraîner une fuite de ressources), il vous incombe de gérer l’exception InterruptedException. C’est à vous de décider si vous voulez que votre fil soit interruptible ou non.

    En d’autres termes, le mécanisme d’interruption est principalement utilisé pour mettre en œuvre les politiques d’annulation et le nettoyage des tâches. Est-ce que vous n’avez rien à nettoyer dans la tâche ou que vous n’avez pas de politique d’annulation de tâche spécifique, ignorer IntrruptedException peut ne pas sembler politiquement correct mais est correct.