Comment interrompre un thread dans un rapide et propre en java?
Voici mon problème: j'ai une boîte de dialogue avec certains paramètres que l'utilisateur peut modifier (via un compteur par exemple). Chaque fois que l'un de ces paramètres est modifié, je lance un fil de mise à jour d'une vue en 3D en fonction de la nouvelle valeur du paramètre.
Si l'utilisateur modifie une autre valeur (ou la même valeur, en cliquant plusieurs fois sur la touche de navigation flèche), tandis que le premier thread de travail, je voudrais annuler le premier thread (et la mise à jour de la vue 3D) et de lancer un nouveau avec la dernière valeur de paramètre.
Comment puis-je faire quelque chose comme ça?
PS: Il n'y a pas de boucle dans le run()
méthode de mon fils, afin de vérifier l'indicateur n'est pas une option: le fil de mise à jour de la vue 3D, fondamentalement, n'appelle qu'une seule méthode qui est très long à exécuter. Je ne peux pas ajouter un drapeau dans cette méthode, en demandant pour abandon, soit que je n'ai pas accès à son code.
- Pouvez-vous nous donner quelques infos sur l'API que vous utilisez? Vous dites que vous soumettre quelque chose à un peu de méthode, à partir d'un 3ème partie de la bibliothèque, et cela prend du temps. Cette méthode de modifier directement l'objet que vous passer? Ou, avez-vous un rappel avec les résultats?
- Ne ce Thread jamais terminé normalement avant que votre application est terminée? Si oui, quelles en sont les causes d'arrêter?
Vous devez vous connecter pour publier un commentaire.
Essayer d'interruption() comme certains l'ont dit pour voir si cela fait une différence pour votre thread. Si pas, essayez de détruire ou de fermeture d'une ressource qui va faire le fil d'arrêt. Qui a une chance d'être un peu mieux que d'essayer de lancer le Thread.stop() à lui.
Si la performance est tolérable, vous pouvez afficher chaque 3D mise à jour comme un discret non-événement interruptible et simplement le laisser fonctionner jusqu'à leur conclusion, de vérifier par la suite si il y a un nouveau dernière mise à jour à effectuer. Cela pourrait faire l'interface graphique un peu agitée pour les utilisateurs, qu'ils seraient en mesure de faire des modifications de cinq, puis de voir les résultats graphiques de la façon dont les choses étaient cinq changements il y a, puis voir le résultat de leur dernière modification. Mais selon combien de temps ce processus, il pourrait être tolérable, et il serait d'éviter d'avoir à tuer le fil. Conception pourrait ressembler à ceci:
Le fil qui est la mise à jour de la vue 3D se doit de vérifier régulièrement certains drapeau (utiliser un
volatile boolean
) pour voir si elle devrait se terminer. Lorsque vous voulez interrompre le fil, il suffit de mettre le drapeau. Lorsque le thread suivant vérifie le drapeau, il faut simplement sortir de ce que la boucle c'est à l'aide de mise à jour de la vue et de retour de sesrun
méthode.Si vous avez vraiment ne peut pas accéder au code du Thread est en cours afin de vérifier un drapeau, alors il n'y a pas de moyen sûr pour arrêter le Fil. Ne ce Thread jamais terminé normalement avant que votre application est terminée? Si oui, quelles en sont les causes d'arrêter?
Si il fonctionne pendant une longue période de temps, et vous devez simplement mettre fin, vous pouvez envisager d'utiliser le obsolète
Thread.stop()
méthode. Toutefois, il est déconseillé pour une bonne raison. Si ce Thread est arrêté au milieu d'une opération qui laisse quelque chose dans un état incohérent ou à certaines ressources ne sont pas nettoyés correctement, alors vous pourriez être en difficulté. Voici une note de la la documentation:Au lieu de rouler votre propre drapeau booléen, pourquoi ne pas simplement utiliser le fil d'interruption mécanisme déjà dans les threads Java? Selon la façon dont les entrailles ont été mises en œuvre dans le code, vous ne pouvez pas modifier, vous pouvez être en mesure d'abandonner une partie de son exécution trop.
Filetage Extérieur:
Intérieure Exécutable/Thread:
N'est-ce pas un peu comme demander "Comment puis-je interrompre un thread quand aucune autre méthode que de Fil.stop() est disponible?"
Évidemment, la seule réponse valable est Thread.stop(). Son laid, pourrait casser des choses dans certaines circonstances, peut conduire à la mémoire de ressources de fuites, et c'est très mal vu par TLEJD (La Ligue Extraordinaire des Développeurs Java), mais il peut encore être utile dans quelques cas comme celui-ci. Il n'y a vraiment pas d'autre méthode si la troisième partie du code n'a pas de certains proches méthode disponible pour elle.
Otoh, que, parfois, il y a de porte dérobée à proximité méthodes. C'est à dire, la fermeture d'un flux sous-jacent qui à son fonctionnement, ou toute autre ressource dont il a besoin pour faire son travail. Ce n'est que rarement mieux que de simplement Thread appelant.stop() et laisser l'expérience d'une ThreadDeathException, cependant.
Accepté la réponse à cette question permet de soumettre des lots de travail dans un thread d'arrière-plan. Ce pourrait être un meilleur modèle pour ça:
L'utilisation de cette classe, l'étendre, en fournissant un type de T et de mise en œuvre de processItem(). Puis il suffit de construire l'un et l'appel de la méthode start() sur elle.
Vous pourriez envisager d'ajouter un abortPending méthode:
pour les cas où l'utilisateur a sauté à l'avance du moteur de rendu et vous voulez jeter le travail qui a été prévu jusqu'à présent.
notifyAll ()
pourworkItems
liste? N'est-il pas suffisant pour définir lastopping
variabletrue
, parce que lerun ()
méthode fonctionne encore?Un thread va sortir une fois qu'il est
run()
méthode est terminée, alors vous devez vérifier ce qui va la faire terminer la méthode.Vous pouvez interrompre le fil, et ensuite, vérifiez ce qui permettrait de vérifier périodiquement
isInterrupted()
et le retour de larun()
méthode.Vous pouvez également utiliser un booléen qui reçoit périodiquement vérifiées dans le thread, et en fait de retour si oui, ou mettre le fil à l'intérieur d'une boucle si il fait un repetative tâche et il va ensuite la sortie de la méthode run() lorsque vous définissez la valeur de type boolean. Par exemple,
Malheureusement tuer un thread est intrinsèquement dangereux en raison de la possibilité d'utiliser des ressources qui peuvent être synchronisés par des verrous et si le thread vous tuer a actuellement un verrou pourrait entraîner dans le programme dans l'impasse (constante essayer d'attraper une ressource qui ne peut être obtenu). Vous aurez à vérifier manuellement s'il doit être tués depuis le fil que vous souhaitez arrêter. Volatile assurer la vérification de la variable de la valeur vraie, plutôt que quelque chose qui peut avoir été stocké précédemment. Sur une note côté du Fil.rejoindre sur la sortie de fil pour vous assurer d'attendre jusqu'à ce que le thread est en train de mourir réellement disparu avant de vous faire quelque chose plutôt que de vérifier tout le temps.
Vous avez l'air de n'avoir aucun contrôle sur le fil qui est du rendu de l'écran, mais vous ne semblent avoir le contrôle de la spinner composant. Je voudrais désactiver le compteur tandis que le thread est rendu à l'écran. De cette façon, l'utilisateur a au moins quelques commentaires relatifs à leurs actions.
Je suggère que vous venez d'éviter que plusieurs Threads en utilisant les attendre et de les informer, de sorte que si l'utilisateur change la valeur du nombre de fois qu'il sera exécuté uniquement le Fil une fois. Si l'utilisateur modifie la valeur de 10 fois, il va déclencher le Fil lors de la première modification, puis toutes les modifications apportées avant le Thread est fait tout obtenir "roulé" dans une seule notification. Qui ne s'arrêtent pas d'un Fil, mais il n'y a pas de bonnes façons de faire en fonction de votre description.
Les solutions que le but de l'utilisation d'un champ booléen sont la bonne direction. Mais le champ doit être volatile.
Le Langage Java Spec dit:
Aussi loin que je me souvienne "Java de la Simultanéité dans la Pratique" fins de l'utilisation de la interrupt() et interrompu() méthodes de java.lang.Fil de discussion.
La façon que j'ai mis en place quelque chose comme cela dans le passé, est de mettre en œuvre un
shutdown()
méthode dans monRunnable
sous-classe qui définit une variable d'instance appeléeshould_shutdown
de vrai. Lerun()
méthode normalement fait quelque chose dans une boucle, et de vérifier régulièrement lesshould_shutdown
et quand il est vrai, des retours ou des appelsdo_shutdown()
et puis revient.Vous devez conserver une référence à l'actuel thread de travail à portée de main, et lorsque l'utilisateur modifie une valeur, appelez
shutdown()
sur le thread en cours, et de l'attendre à l'arrêt. Ensuite, vous pouvez lancer un nouveau thread.Je vous déconseille d'utiliser
Thread.stop
comme il a été rendu obsolète la dernière fois que j'ai vérifié.Edit:
Lire votre commentaire à propos de la façon dont votre thread appelle simplement une autre méthode qui prend un certain temps à s'exécuter, de sorte que le ci-dessus ne s'applique pas. Dans ce cas, votre seul véritable options sont d'essayer d'appeler
interrupt()
et voir si a aucun effet. Si pas, envisager quelque sorte manuellement provoquer de la fonction de votre thread de travail est l'appel à la rupture. Par exemple, on dirait qu'elle est en train de faire certains complexes de rendu, donc peut-être détruire la toile et de l'amener à lever une exception. Ce n'est pas une solution sympa, mais autant que je peux dire, ce est la seule façon d'arrêter un thread dans suituations comme ça.Puisque vous avez affaire avec le code que vous n'avez pas accès, vous êtes probablement hors de la chance. La procédure standard (comme indiqué dans les autres réponses) est d'avoir un drapeau qui est vérifié périodiquement par le thread en cours d'exécution. Si le drapeau est réglé, procéder au nettoyage et à la sortie.
Depuis que l'option n'est pas disponible pour vous, la seule autre option est de les forcer à quitter le processus en cours d'exécution. C'est possible en appelant Fil de discussion.stop(), mais cette méthode a été définitivement supprimée pour la raison suivante (copié à partir de la documentation javadoc):
Plus d'informations sur ce sujet peuvent être trouvées ici.
Un absolu moyen sûr de vous pourriez faire votre demande (même si ce n'est pas un moyen très efficace de le faire) est de commencer un nouveau processus java via Moment de l'exécution.exec() et l'arrêt de ce processus en tant que nécessaire via Processus.destroy(). L'état de partage entre les processus comme ce n'est pas exactement banal, cependant.
Au lieu de jouer avec le fil de départ et d'arrêt, avez-vous envisagé d'avoir le fil d'observer les propriétés que vous passez par le biais de votre interface? Vous allez à un certain point encore envie d'une condition d'arrêt pour votre thread, mais cela peut être fait, ce fut ainsi. Si vous êtes un fan de la MVC, cela s'intègre bien dans ce genre de conception
Désolé, après re-lecture de votre question, ni le présent, ni l'une de l'autre "vérifier la variable" suggestions pour résoudre votre problème.
La bonne réponse est de ne pas utiliser un fil.
Vous devriez être en utilisant les Exécuteurs testamentaires, pour voir l'emballage: java.util.simultanées
Peut-être cela peut vous aider: Comment peut-on tuer un thread en cours d'exécution en Java?