Comment faire pour savoir si d'autres threads ont fini?
J'ai un objet avec une méthode nommée StartDownload()
, qui commence à trois fils.
Comment puis-je obtenir une notification chaque thread a fini de s'exécuter?
Est-il un moyen de savoir si l'un (ou l'ensemble) de la thread est terminé ou est encore en cours d'exécution?
- Jetez un oeil à la Java 5 Barrière de classe
Vous devez vous connecter pour publier un commentaire.
Il y a un certain nombre de façons dont vous pouvez faire ceci:
Comment mettre en œuvre l'Idée #5? Eh bien, une façon est d'abord de créer une interface:
puis créer la classe suivante:
et puis chacun de vos Fils va étendre
NotifyingThread
et au lieu de la mise en œuvre derun()
il va mettre en placedoRun()
. Ainsi, lorsqu'ils ont terminé, ils seront automatiquement le signaler à quelqu'un en attente de notification.Enfin, dans votre classe principale -- celui qui commence tous les Threads (ou au moins l'objet en attente de notification) -- modifier la classe de
implement ThreadCompleteListener
et immédiatement après la création de chaque Thread s'ajouter à la liste des auditeurs:puis, comme chaque Thread s'arrête, votre
notifyOfThreadComplete
méthode sera invoquée avec le Fil de l'instance qui vient de se terminer (ou écrasé).Noter que le mieux serait de
implements Runnable
plutôt queextends Thread
pourNotifyingThread
comme une extension de l'Thread est généralement déconseillé dans le nouveau code. Mais je suis de codage à votre question. Si vous modifiez leNotifyingThread
classe pour mettre en œuvreRunnable
alors vous devez changer certaines de vos code qui gère les Threads, ce qui est assez simple à faire.notify
méthode pas insinde larun
méthode, mais d'après elle.Solution à l'aide de CyclicBarrier
label0 - cyclique de la barrière est créé avec le nombre de parties égal au nombre de l'exécution de threads, plus un pour le thread principal d'exécution (dans lequel startDownload() est exécutée)
étiquette 1 - n-ième DownloadingThread entre dans la salle d'attente
label 3 - NUMBER_OF_DOWNLOADING_THREADS avez entré dans la salle d'attente. Thread principal d'exécution des rejets à commencer à faire de leur téléchargement des emplois plus ou moins dans le même temps
label 4 - thread principal d'exécution entre dans la salle d'attente. C'est la plus délicate de la partie du code à comprendre. Il n'a pas d'importance thread qui va entrer dans la salle d'attente pour la deuxième fois. Il est important que tout ce thread entre dans la salle dernier s'assure que tous les autres de télécharger les threads ont fini leur téléchargement emplois.
étiquette 2 - n-ième DownloadingThread a fini son téléchargement du travail et entre dans la salle d'attente. Si c'est le dernier, c'est à dire déjà NUMBER_OF_DOWNLOADING_THREADS la saisie, y compris le thread principal de l'exécution, le thread principal continuera son exécution que lorsque tous les autres threads avez terminé le téléchargement.
Vous devriez vraiment préférez une solution qui utilise
java.util.concurrent
. Trouver et lire Josh Bloch et/ou de Brian Goetz sur le sujet.Si vous n'êtes pas à l'aide de
java.util.concurrent.*
et prennent la responsabilité pour l'utilisation de Threads directement, alors vous devriez probablement utiliserjoin()
de savoir quand un thread est fait. Ici est super simple mécanisme de Rappel. Tout d'abord étendre leRunnable
interface d'avoir un rappel:Puis faire un Exécuteur testamentaire qui exécutera votre exécutable et vous rappeler quand il est fait.
L'autre le genre de chose évidente à ajouter à votre
CallbackRunnable
interface est un moyen de gérer toutes les exceptions, donc peut-être mettre unpublic void uncaughtException(Throwable e);
ligne là-bas et à votre exécuteur testamentaire, d'installer un Fil.UncaughtExceptionHandler de vous envoyer à l'interface de la méthode.Mais le faire tous ça commence vraiment à sentir comme
java.util.concurrent.Callable
. Vous devriez vraiment regarder à l'aide dejava.util.concurrent
si votre projet le permet.runner.join()
et ensuite le code que vous voulez après que, puisque vous savez que le thread a fini. Est-il juste que vous obtenez pour définir ce code comme une propriété de l'exécutable, de sorte que vous peut avoir différentes choses pour différentes runnables?runner.join()
est le moyen le plus direct d'attendre. J'ai été en supposant que les OP ne voulez pas bloquer leur principal thread appelant depuis ils ont demandé à être "averti" pour chaque téléchargement, ce qui pourrait remplir dans n'importe quel ordre. Ce programme offre un moyen d'être averti de manière asynchrone.Voulez-vous de les attendre à la fin? Si oui, utiliser la méthode de participation.
Il y a aussi la propriété isAlive si vous voulez juste pour vérifier.
Thread
àstart
, qui le thread n', mais l'appel retourne immédiatement.isAlive
devrait être un simple indicateur de test, mais quand je l'ai googlé la méthode a éténative
.Vous pouvez interroger le fil de l'instance avec getState() qui retourne une instance de Thread.État de l'énumération avec l'une des valeurs suivantes:
Cependant, je pense que ce serait un meilleur design afin d'avoir un maître thread qui attend les 3 enfants à la fin, le maître serait alors poursuivre l'exécution lorsque les 3 autres ont fini.
Je suggère de regarder à la javadoc de Fil classe.
Vous disposez de plusieurs mécanismes pour le fil de la manipulation.
Votre thread principal peut
join()
les trois fils en série, et serait alors de ne pas continuer jusqu'à ce que tous les trois sont fait.Sondage de l'état du thread de l'engendré de fils à des intervalles.
Mettre toutes les donné naissance à des threads dans un distinct
ThreadGroup
et interroger leactiveCount()
sur leThreadGroup
et d'attendre pour elle d'obtenir à 0.L'installation d'une fonction de rappel personnalisée ou de l'auditeur type de l'interface pour la communication inter-thread.
Je suis sûr qu'il ya beaucoup d'autres façons je suis toujours portées disparues.
Vous pouvez également utiliser la
Executors
objet pour créer un ExecutorService pool de threads. Ensuite, utilisez lainvokeAll
méthode à exécuter chacun de vos fils et de récupérer à Terme. Cela va bloquer jusqu'à ce que tous aient fini de l'exécution. Votre autre option consisterait à exécuter chaque utilisation de la piscine et ensuite appelerawaitTermination
à bloc jusqu'à ce que la piscine est terminée en cours d'exécution. Juste être sûr de faire appelshutdown
() lorsque vous avez fini d'ajouter des tâches.Beaucoup de choses ont changé au cours des 6 dernières années sur le multi-threading avant.
Au lieu d'utiliser
join()
et de verrouillage de l'API, vous pouvez utiliser1.ExecutorService
invokeAll()
API2.CountDownLatch
3.ForkJoinPool ou
newWorkStealingPool()
dans Les exécuteurs est d'autre moyen4.Itérer sur tous les
Future
tâches de présenter surExecutorService
et de vérifier le statut à l'appel de blocageget()
surFuture
objetRegarder liées SE questions:
Comment attendre un thread qui fraie son propre thread?
Les exécuteurs: Comment de façon synchrone attendre jusqu'à ce que toutes les tâches ont terminé si des tâches sont créées de manière récursive?
Voici une solution qui est simple, court, facile à comprendre, et fonctionne parfaitement pour moi. J'ai besoin de dessiner à l'écran quand un autre thread se termine; mais je ne pouvais pas parce que le thread principal est le contrôle de l'écran. Donc:
(1) j'ai créé la variable globale:
boolean end1 = false;
Les ensembles de fil à true quand la fin de. C'est ramassé dans la mainthread par "postDelayed" en boucle, où il est répondu.(2) Mon thread contient:
(3) Heureusement, "postDelayed" s'exécute dans le thread principal, c'est de là qu'en vérifier l'autre thread une fois chaque seconde. Quand l'autre thread se termine, cela peut commencer à tout ce que nous voulons faire.
(4) Enfin, commencer le tout fonctionnant quelque part dans votre code en appelant:
Je suppose que le plus simple est d'utiliser
ThreadPoolExecutor
classe.qui est exactement ce dont nous avons besoin. Nous allons remplacer
afterExecute()
pour obtenir les rappels après chaque thread est fait et sera remplacerterminated()
à savoir, lorsque tous les threads sont fait.Donc, voici ce que vous devez faire
Créer un exécuteur testamentaire:
Et de commencer votre fils:
À l'intérieur de la méthode
informUiThatWeAreDone();
faire ce que vous devez faire lorsque tous les threads sont fait, par exemple, la mise à jour de l'INTERFACE utilisateur.REMARQUE: Ne pas oublier d'utiliser
synchronized
méthodes depuis que vous faites votre travail en parallèle et ÊTRE TRÈS PRUDENT si vous décidez d'appelersynchronized
méthode à partir d'un autresynchronized
méthode! Cela conduit souvent à des blocagesEspérons que cette aide!
Vous pouvez également utiliser SwingWorker, qui a été intégrée à la propriété de changer de support. Voir addPropertyChangeListener() ou la get() méthode pour un changement d'état de l'écouteur exemple.
Oeil à la documentation de Java de la classe Thread. Vous pouvez vérifier l'état du fil. Si vous mettez les trois fils dans des états variables, puis tous les trois threads peuvent lire des uns et des autres états.
Vous devez être un peu prudent, cependant, parce que vous pouvez provoquer des conditions de course entre les threads. Essayez simplement d'éviter compliqué logique basée sur l'état des autres threads. Certainement éviter plusieurs threads d'écriture pour les mêmes variables.