Comment bien arrêter le Thread en Java?
J'ai besoin d'une solution pour bien arrêter le thread en Java.
J'ai IndexProcessor
classe qui implémente l'interface Runnable:
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
@Override
public void run() {
boolean run = true;
while (run) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
run = false;
}
}
}
}
Et j'ai ServletContextListener
classe qui démarre et arrête le thread:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
@Override
public void contextInitialized(ServletContextEvent event) {
thread = new Thread(new IndexProcessor());
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
thread.interrupt();
LOGGER.debug("Thread successfully stopped.");
}
}
}
Mais quand j'ai arrêté de tomcat, j'obtiens une exception dans mon IndexProcessor classe:
2012-06-09 17:04:50,671 [Thread-3] ERROR IndexProcessor Exception
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at lt.ccl.searchengine.processor.IndexProcessor.run(IndexProcessor.java:22)
at java.lang.Thread.run(Unknown Source)
Je suis à l'aide de JDK 1.6. La question est donc:
Comment puis-je arrêter le fil et ne pas jeter des exceptions?
P. S. je ne veux pas utiliser .stop();
méthode, car il est obsolète.
- Mettre fin à un thread de la moitié du chemin sera toujours générer une exception. Si c'est un comportement normal, il vous suffit de les attraper et de les ignorer l'
InterruptedException
. C'est ce que je pense, mais je me demande aussi comment le standard est. - Comment sur l'utilisation de
join()
? - Je n'ai pas été à l'aide de threads, très souvent, donc je suis assez nouveau de threads, donc je ne sais pas si c'est le comportement normal d'ignorer l'exception. C'est pourquoi je demande.
- Dans de nombreux cas, c'est le comportement normal d'ignorer l'exception et de mettre fin à la méthode de traitement. Voir ma réponse ci-dessous pour savoir pourquoi cela est bettern qu'une approche basée sur l'indicateur.
- Une explication soignée par B. Goetz concernant
InterruptedException
peut être trouvé à l'adresse ibm.com/developerworks/library/j-jtp05236. - le InterruptedException n'est pas un problème, le seul problème dans la posté code est vous ne devriez pas vous connecter, il y a comme une erreur, il n'y a vraiment pas de raison convaincante pour le journal comme tous sauf de débogage juste pour démontrer qu'il s'est passé dans le cas où vous êtes intéressé. la réponse sélectionnée est regrettable, car il ne permet pas de couper court à des appels à des appels tels que le sommeil et d'attendre.
InformationsquelleAutor Paulius Matulionis | 2012-06-09
Vous devez vous connecter pour publier un commentaire.
Dans le
IndexProcessor
classe vous avez besoin d'un moyen de définir un indicateur qui informe le fil qu'il faudra mettre fin, de façon similaire à la variablerun
que vous avez utilisé seulement dans le domaine de la classe.Lorsque vous souhaitez arrêter le fil, vous activez ce code et d'appel
join()
sur le fil et attendre qu'elle se termine.Assurez-vous que le drapeau est thread-safe en utilisant une variable volatile ou en utilisant les méthodes getter et setter qui sont synchronisés avec la variable utilisée comme indicateur.
Puis dans
SearchEngineContextListener
:Waits for this thread to die.
ce n'est pas près de la même chose que arrêt le fil.while
commewhile(true)
au lieu dewhile(running)
(long) 123
n'est pas nécessaire. Il suffit de ne123L
ou123l
terminate()
sur chaque instance de), vous pouvez modifier larunning
membre et leterminate()
méthode pourstatic
et de cette façon, un seul appel àIndexProcess.terminate()
de résilier tous d'entre eux.À l'aide de
Thread.interrupt()
est une très bonne façon de le faire. En fait, il est probablement préférable à un indicateur comme suggéré ci-dessus. La raison en est que si vous êtes dans une interruptable appel de blocage (commeThread.sleep
ou à l'aide de java.nio Canal d'activités), vous aurez en fait être en mesure de sortir de ceux-là.Si vous utilisez un drapeau, vous devez attendre pour l'opération de blocage à la fin et puis vous pouvez vérifier votre drapeau. Dans certains cas, vous devez le faire de toute façon, comme l'utilisation de la norme
InputStream
/OutputStream
qui ne sont pas interruptable.Dans ce cas, lorsqu'un thread est interrompu, il n'interrompt pas le IO, cependant, vous pouvez facilement le faire régulièrement dans votre code (et vous devriez le faire à des endroits stratégiques où vous pouvez vous arrêter et de nettoyage)
Comme je l'ai dit, le principal avantage de
Thread.interrupt()
est que vous pouvez immédiatement sortir de interruptable appels, que vous ne pouvez pas faire avec le drapeau de l'approche.interrupt()
peut être ok, mais dans beaucoup d'autres cas, il n'est pas (par exemple, si une ressource doit être fermé). Si quelqu'un des changements à l'intérieur de la boucle, vous devez vous rappeler de changer leinterrupt()
booléenne façon. Je voudrais aller en toute sécurité à partir du début et de l'utilisation de l'indicateur.isInterrupted
de pavillon dans la boucle while n'est pas préférable de provoquer code ailleurs pourrait interrompre le fil. à l'aide d'unrunning
drapeau pouvez éviter ce problème. droit? Je dis cela parce que je me sens votre consolidés ont de multiples interprétations contradictoires.Réponse Simple:
Vous pouvez arrêter un thread en INTERNE dans l'une des deux façons courantes:
Vous pouvez également arrêter les threads de l'EXTÉRIEUR:
system.exit
(ce qui tue l'ensemble de vos processus)interrupt()
méthode *kill()
oustop()
)*: On s'attend à ce que cela est censé arrêter un thread. Cependant, ce que le fil ne fait lorsque cela se produit est entièrement jusqu'à ce que le développeur a écrit lorsqu'ils ont créé le thread de mise en œuvre.
Un modèle commun vous voir avec méthode run implémentations est un
while(boolean){}
, où le booléen est généralement quelque chose nomméisRunning
, c'est une variable de membre de sa classe thread, c'est volatile, et généralement accessibles par d'autres threads par une méthode de définition de toutes sortes, par exemplekill() { isRunnable=false; }
. Ces sous-programmes sont bien car ils permettent le fil pour libérer les ressources qu'il détient, avant de s'arrêter.Vous devriez toujours fin des threads en cochant la case dans la
run()
boucle (le cas échéant).Votre fil devrait ressembler à ceci:
Ensuite, vous pouvez mettre fin à la thread en appelant
thread.stopExecuting()
. De cette façon, le thread est terminé propre, mais cela prend jusqu'à 15 secondes (en raison de votre sommeil).Vous pouvez toujours appeler le thread.interrupt() si c'est vraiment urgent, mais la préférence doit toujours être la vérification de l'indicateur.
Pour éviter un temps d'attente de 15 secondes, vous pouvez diviser le sommeil comme ceci:
Thread
-- il met en œuvreRunnable
-- vous ne pouvez pas appelerThread
méthodes sur elle, sauf si vous déclarez en tant queThread
dans ce cas, vous ne pouvez pas appelerstopExecuting()
Si nous sommes à l'aide du JDK 1.0 , on peut appeler du Thread obsolète méthode stop() pour y mettre fin. À l'aide de stop() est extrêmement dangereuse, car elle va tuer votre fil, même si c'est au milieu de quelque chose d'important. Il n'y a aucun moyen de vous protéger, donc si vous repérez le code qui utilise stop(), vous devriez froncer les sourcils.
Comment l'arrêt d'un thread proprement?
En Java, le démarrage d'un fils est facile, mais à la fermeture nécessitent beaucoup d'attention et d'efforts.
Ici est de savoir comment il est conçu en Java. Il y a un drapeau appelé Interruption de l'indicateur d'état dans chaque fil de java que l'on peut définir à partir de l'extérieur, c'est à dire le parent ou le thread principal. Et le fil peut vérifier de temps en temps et s'arrête. Volontairement..!! Voici comment:
source: Comment arrêter le thread en java | MultiThreading
Pour la synchronisation des threads, je préfère utiliser
CountDownLatch
qui aide les threads d'attendre jusqu'à ce que le processus complet exécuté. Dans ce cas, le travailleur de la classe est mis en place avec unCountDownLatch
exemple avec un comte. Un appel àawait
méthode bloquera jusqu'à ce que le compte à rebours atteint zéro, suite aux interpellations de lacountDown
méthode ou que le délai fixé est atteint. Cette approche permet d'interrompre un thread instantanément sans avoir à attendre pour le temps d'attente indiqué de s'écouler:Quand vous voulez à la fin de l'exécution de l'autre fil, exécutez compte à rebours sur le
CountDownLatch
etjoin
le thread le thread principal:Quelques infos supplémentaires.
Du pavillon et de l'interruption sont proposées dans la Java doc.
https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Pour un thread qui attend pour de longues périodes (par exemple, pour l'entrée), l'utilisation
Thread.interrupt
Je n'ai pas l'interruption de travail sur Android, j'ai donc utilisé cette méthode, fonctionne parfaitement:
volatile
. Voir docs.oracle.com/javase/specs/jls/se9/html/jls-17.html#jls-17.3.Généralement, un thread est terminé quand il est interrompu. Alors, pourquoi ne pas utiliser la boolean natif? Essayez isInterrupted():
ref- Comment puis-je tuer un thread? sans l'aide de stop();