Qui appelle la méthode d’interruption Java Thread si je ne le suis pas?

J’ai lu et relu Java Concurrency en pratique, j’ai lu plusieurs articles sur le sujet, j’ai lu l’article d’IBM traitant d’InterruptedException et pourtant, il y a quelque chose que je ne saisis pas, qui peut être cassé en deux questions:

  1. Si je n’arrive jamais à interrompre moi-même d’autres threads, qu’est-ce qui peut déclencher une exception d’ interruption ?

  2. Si je ne suis jamais en train d’interrompre moi-même d’autres threads en utilisant interrupt () (dis parce que j’utilise d’autres moyens pour annuler mes threads de travail, comme des poisons et une boucle de style (! une exception d’ interruption signifie-t-elle alors? Que dois-je faire en attrapant un? Arrêter mon application?

Le mécanisme d’interruption de thread est le moyen préféré pour obtenir un thread (coopérant) pour répondre à une requête afin d’arrêter ce qu’il est en train de faire. Tout thread (y compris le thread lui-même, je pense) pourrait appeler interrupt() sur un thread.

En pratique, les cas d’utilisation normaux d’ interrupt() impliquent une sorte de framework ou de gestionnaire indiquant à un thread de travail d’arrêter ce qu’il fait. Si le thread de travail est “interrupt collaboration”, il remarquera qu’il a été interrompu via une exception ou en vérifiant périodiquement son drapeau interrompu. En remarquant qu’il a été interrompu, un fil bien comporté abandonnerait ce qu’il fait et se terminerait lui-même.

En supposant le cas d’utilisation ci-dessus, votre code est susceptible d’être interrompu s’il est exécuté dans un framework Java ou à partir d’un thread de travail. Et quand il est interrompu, votre code devrait abandonner ce qu’il fait et se terminer par les moyens les plus appropriés. Selon la manière dont votre code a été appelé, cela peut être fait en renvoyant 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 ya d’autres threads qui doivent être interrompus par le framework.)

D’un autre côté, si votre code n’est pas conçu pour s’exécuter sous le contrôle d’un framework, vous pourriez soutenir que l’exception InterruptedException est une exception inattendue. c’est à dire un bug. Dans ce cas, vous devez traiter l’exception comme vous le feriez avec d’autres bogues. Par exemple, enveloppez-le dans une exception non cochée et attrapez-le et connectez-le au même point que vous traitez avec d’autres exceptions non vérifiées inattendues. (Sinon, votre application pourrait simplement ignorer l’interruption et continuer à faire ce qu’elle faisait).


1) Si je n’interromps jamais d’autres threads, qu’est-ce qui peut déclencher une exception d’interruption?

Par exemple, si vos objects Runnable sont exécutés à l’aide d’un ExecutorService et que shutdownNow() est appelé sur le service. Et en théorie, tout pool de threads ou framework de threads tiers pourrait légitimement faire quelque chose comme ça.

2) Si je n’interromps jamais les autres threads moi-même en utilisant interrupt () … que signifie alors une InterruptedException ? Que dois-je faire en attrapant un? Arrêter mon application?

Vous devez parsingr la base de code pour déterminer ce qui fait les appels d’ interrupt() et pourquoi. Une fois que vous avez compris cela, vous pouvez déterminer ce que >> votre partie de l’application doit faire.

Tant que vous ne savez pas pourquoi InterruptedException est lancé, je vous conseille de le traiter comme une erreur grave. Par exemple, imprimez une stack dans le fichier journal et fermez l’application. (Évidemment, ce n’est pas toujours la bonne réponse… mais le fait est qu’il s’agit d’un “bug”, et qu’il doit être porté à l’attention du développeur / mainteneur.)

3) Comment savoir qui / quoi appelle interrupt() ?

Il n’y a pas de bonne réponse à cela. Le mieux que je puisse suggérer est de définir un point d’arrêt sur le Thread.interrupt() et d’examiner la stack d’appels.

Si vous décidez d’intégrer votre code à d’autres bibliothèques, ils peuvent appeler interrupt() sur votre code. Par exemple, si vous décidez à l’avenir d’exécuter votre code dans un ExecutorService , cela peut forcer un arrêt via interrupt() .

Pour le dire brièvement, je considérerais non seulement où votre code s’exécute maintenant , mais dans quel contexte il pourrait fonctionner dans le futur. par exemple allez-vous le mettre dans une bibliothèque? Un contenant ? Comment les autres vont-ils l’utiliser? Allez-vous le réutiliser?

Comme d’autres l’ont fait remarquer, 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 une InterruptedException comme une “commande de fermeture”. Au lieu de cela, vous devriez penser aux interruptions comme un moyen de contrôler le statut d’exécution des threads, de la même manière que Object.notify() . De la même manière que vous vérifiez l’état actuel après vous être réveillé d’un appel à Object.wait() (vous ne présumez pas que le réveil signifie que votre condition d’attente a été satisfaite), après avoir été interrompu par une interruption, vous devriez vérifiez pourquoi vous avez été interrompu. Il existe généralement un moyen de le faire. Par exemple, java.util.concurrent.FutureTask a une méthode isCancelled() .

Échantillon 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(); } 

Le problème avec la question est “je”. “Je” se réfère généralement à une instance unique d’une classe. Je veux dire par là que tout élément de code de bas niveau (classe) ne devrait pas dépendre de l’implémentation de l’ensemble du système. Cela dit, vous avez pris des décisions «architecturales» (comme sur quelle plate-forme).

Les interruptions inattendues possibles provenant du JRE sont des tâches annulées dans java.util.concurrent et la fermeture des applets.

Le traitement des interruptions de thread est généralement mal écrit. Par conséquent, je suggère la décision architecturale pour éviter de provoquer des interruptions dans la mesure du possible. Cependant, les interruptions de manipulation de code doivent toujours être écrites correctement. Ne peut pas prendre les interruptions de la plate-forme maintenant.

Vous pouvez apprendre cela en créant votre propre classe de thread (extension de java.lang.Thread ) et en remplaçant la méthode interrupt() , dans laquelle vous enregistrez la trace dans un champ Ssortingng, puis vous transférez dans super.interrupt ().

 public class MyThread extends Thread { public volatile Ssortingng interruptStacktrace; // Temporary field for debugging purpose. @Override public void interrupt() { interruptStacktrace = dumpStack(); // You implement it somehow... super.interrupt(); } } 

Comme déjà mentionné, une autre bibliothèque peut interrompre vos discussions. Même si la bibliothèque n’a pas d’access explicite aux threads de votre code, ils peuvent toujours obtenir la liste des threads en cours d’exécution et les interrompre de cette manière avec la méthode suivante.

L’ InterruptedException indique qu’une routine peut être interrompue, mais pas nécessairement.

Si vous n’attendez pas l’interruption, vous devriez la traiter comme n’importe quelle autre exception inattendue. Si elle se trouve dans une section critique où une exception imprévue pourrait avoir des conséquences désastreuses, il serait préférable d’essayer de nettoyer les ressources et d’arrêter normalement (car le signal d’interruption indique que votre application bien conçue ne reposant pas sur des interruptions est utilisée) dans un sens, il n’a pas été conçu et il doit donc y avoir quelque chose qui ne va pas. Sinon, si le code en question est quelque chose de non critique ou sortingvial, vous pouvez ignorer (ou enregistrer) l’interruption et continuer.

Je pense que je comprends pourquoi vous êtes un peu confus au sujet de l’interruption. Veuillez considérer mes réponses en ligne:

Si je n’arrive jamais à interrompre moi-même d’autres threads, qu’est-ce qui peut déclencher une exception d’ interruption ?

Tout d’abord, vous pouvez interrompre d’autres threads; Je sais que dans JCiP, il est mentionné que vous ne devez jamais interrompre les threads que vous ne possédez pas; Cependant, cette déclaration doit être bien comprise. Cela signifie que votre code qui pourrait s’exécuter dans un thread arbitraire ne devrait pas gérer les interruptions, car comme il n’est pas le propriétaire du thread, il n’a aucune idée de sa politique d’interruption. Vous pouvez donc demander une interruption sur d’autres threads, mais laissez son propriétaire prendre des mesures d’interruption. la politique d’interruption est encapsulée dans celui-ci, pas votre code de tâche; au moins soyez courtois pour définir le drapeau d’interruption!

Il y a beaucoup de raisons pour lesquelles il pourrait y avoir encore des interruptions, peut-être des délais, des interruptions de la JVM, etc.

Si je ne suis jamais en train d’interrompre moi-même d’autres threads en utilisant interrupt () (dis parce que j’utilise d’autres moyens pour annuler mes threads de travail, comme des poisons et une boucle de style (! une exception d’interruption signifie-t-elle alors? Que dois-je faire en attrapant un? Arrêter mon application?

Vous devez faire très attention ici; Si vous possédez le thread qui a lancé InterruptedException (IE), alors vous savez quoi faire si vous le rattrapez, vous pouvez arrêter votre application / service ou remplacer ce thread par un nouveau! Cependant, si vous ne possédez pas le thread, puis attrapez IE, soit le redirect vers le haut de la stack d’appels, soit après avoir fait quelque chose (peut-être la journalisation), réinitialisez l’état pour que le code apprenez que le thread a été interrompu et que, par conséquent, il agira comme il le fera puisque seul il connaît la politique d’interruption.

J’espère que cela a aidé.