L'obtention de la sortie d'un Thread
Que pensez-vous est la meilleure façon d'obtenir les résultats des travaux d'un thread? Imaginez un Thread qui effectue des calculs, comment faire pour vous avertir que le programme principal, les calculs sont effectués?
Vous pourriez sondage toutes les X millisecondes pour certains publics variable appelée "travail terminé" ou quelque chose en chemin, mais ensuite, vous recevrez les résultats par la suite que quand il serait disponible... le code principal serait de perdre de temps à attendre pour eux. D'autre part, si vous utilisez une baisse des X, le CPU serait perdu d'interrogation à de nombreuses reprises.
Alors, que faites-vous pour être au courant que le Thread, ou certains Threads, ont terminé leur travail?
Désolé si ça ressemble à ce que d'autres question, c'est probablement la raison pour laquelle le eben réponse, je suppose. Ce que je sensés était en cours d'exécution beaucoup de fils et de savoir quand toutes ont fini, sans interrogation.
Je pensais plus à la ligne de partage de la charge du PROCESSEUR entre plusieurs CPU à l'aide de lots de Fils, et de savoir quand un lot est terminé. Je suppose que cela peut être fait avec Avenirs objets, mais que le blocage de la obtenir méthode ressemble beaucoup à un verrou caché, pas quelque chose que j'aime.
Merci à tous pour votre soutien. Bien que j'ai aussi aimé la réponse par erickson, je pense que saua's le plus complet, et celui que je vais utiliser dans mon propre code.
>, et de savoir quand un lot est terminé. Pourquoi voulez-vous le savoir? Avez-vous besoin de quelque chose à partir de ce Lot? Ou voulez-vous pour savoir quand vous pouvez shedule plus de Tâches?
OriginalL'auteur Saiyine | 2008-12-09
Vous devez vous connecter pour publier un commentaire.
Ne pas utiliser de bas niveau des structures telles que les threads, sauf si vous avez absolument besoin de la puissance et de la flexibilité.
Vous pouvez utiliser un ExecutorService comme le ThreadPoolExecutor à soumettre() Callables. Cela renvoie un L'avenir objet.
L'aide que
Future
objet que vous pouvez facilement vérifier si c'est fait et obtenir le résultat (y compris un blocageget()
si ce n'est pas encore fait).Ces constructions seront grandement simplifier le plus commun filetée opérations.
Je tiens à préciser sur le blocage
get()
:L'idée est que vous voulez exécuter certaines tâches (la
Callable
s) que faire un peu de travail (calcul, l'accès aux ressources, ...) où vous n'avez pas besoin du résultat droit. Vous pouvez juste dépendra de laExecutor
pour exécuter votre code à chaque fois qu'il veut (si c'est unThreadPoolExecutor
ensuite, il sera exécuté à chaque fois qu'un Thread libre est disponible). Puis à un certain point dans le temps, vous avez probablement , le résultat du calcul de continuer. À ce stade, vous êtes censé appelerget()
. Si la tâche déjà couru à ce point, alorsget()
va juste retourner la valeur immédiatement. Si la tâche n'est pas terminée, puis laget()
appel d'attendre jusqu'à ce que la tâche est terminée. C'est généralement nécessaire puisque vous ne pouvez pas continuer sans les tâches de suite de toute façon.Lorsque vous n'avez pas besoin de la valeur de continuer, mais voudrais savoir si il est déjà disponible (éventuellement montrer quelque chose dans l'INTERFACE utilisateur), alors vous pouvez facilement appeler
isDone()
et appelerget()
si qui retournetrue
).OriginalL'auteur Joachim Sauer
Vous pouvez créer un lister interface que le programme principal met en œuvre ce qui est appelé par le travailleur une fois qu'il a fini de s'exécuter, c'est le travail.
De cette façon, vous n'avez pas besoin de sondage à tous.
Voici un exemple d'interface:
Voici un exemple de la réelle thread qui effectue des travaux, et la notifie auditeurs:
Et enfin, le programme principal qui démarre un thread de travail et les registres d'un auditeur à être informé une fois que le travail est fait:
OriginalL'auteur Neal Donnan
Une interrogation.k.une longue attente n'est pas une bonne idée. Comme vous l'avez mentionné, occupé attente déchets de cycles CPU et peut causer votre application ne répond pas.
Mon Java est rude, mais vous voulez quelque chose comme ce qui suit:
Si un thread a attendre la sortie d'un autre fil, vous utilisez une variable de condition.
Le fil intéressés à la sortie de la menace doit appeler
cv.wait()
. Cela va entraîner le thread en cours à bloc. Lorsque le thread de travail est terminé de travail, elle doit appelercv.signal()
. Cela va entraîner le thread bloqué à se débloquer, lui permettant d'inspecter la sortie de la thread de travail.OriginalL'auteur AlfaZulu
Comme une alternative à la simultanéité de l'API tel que décrit par Saua (et si le thread principal n'a pas besoin de savoir quand un thread se termine), vous pouvez utiliser le modèle de publication/abonnement.
Dans ce scénario, l'enfant
Thread
/Runnable
est donné un auditeur qui sait comment traiter le résultat et qui est appelée lorsque l'enfantThread
/Runnable
complète.OriginalL'auteur Nick Holt
Votre scénario est encore un peu floues.
Si vous exécutez un lot de travail, vous pouvez utiliser
invokeAll
. Cela va bloquer votre thread principal jusqu'à ce que toutes les tâches sont terminées. Il n'y a pas de "busy waiting" avec cette approche, où le thread principal serait déchets CPU interrogation de laisDone
la méthode de l'Avenir. Bien que cette méthode renvoie une liste deFutures
, ils sont déjà "fait". (Il y a aussi une version surchargée qui peut le délai d'attente avant la fin, qui pourrait être plus sûr à utiliser avec certaines tâches.) Cela peut être beaucoup plus propre que d'essayer de rassembler un tas deFuture
objets vous-même et d'essayer de vérifier leur statut ou de bloquer sur leurget
méthodes individuellement.Si c'est une application interactive, avec des tâches de façon sporadique défaite pour être exécuté en arrière-plan, à l'aide d'un rappel comme suggéré par nick.holt est une bonne approche. Ici, vous utilisez le
envoyer
unRunnable
. Lerun
méthode appelle la fonction de rappel avec le résultat quand il a été calculé. Avec cette approche, vous pouvez jeter leFuture
retourné parsubmit
, sauf si vous voulez être en mesure decancel
tâches en cours d'exécution sans l'arrêt duExecutorService
.Si vous voulez être en mesure d'annuler les tâches ou d'utiliser le délai d'attente des capacités, une chose importante à retenir est que les tâches sont annulés par l'appel de
interrompre
sur leur fil. Donc, votre tâche doit vérifier son état d'interruption périodiquement l'abandon et en tant que de besoin.OriginalL'auteur erickson
Sous-classe de Thread, et donner à votre classe une méthode qui retourne le résultat. Lorsque la méthode est appelée, si le résultat n'a pas été créé, pour l'instant, alors join() avec le Fil. Lorsque join() renvoie, votre Thread de travail qui va être fait et le résultat devrait être disponible; return.
À n'utiliser que si vous avez réellement besoin de déclencher une asynchrones activité, faire un peu de travail alors que vous êtes en attente, puis obtenir le résultat. Sinon, quel est le but de ce Thread? Vous pourriez tout aussi bien écrire une classe qui fait le travail et renvoie le résultat dans le thread principal.
Une autre approche serait un rappel: votre constructeur de prendre un argument qui implémente une interface avec une méthode de callback qui sera appelée lorsque le résultat est calculé. Cela rendra le travail complètement asynchrone. Mais si vous à tous les besoin d'attendre le résultat à certains point, je pense que vous allez encore avoir besoin d'appeler join() du thread principal.
OriginalL'auteur skiphoppy
Comme l'a noté saua: utilisez les constructions offertes par java.util.de façon concomitante. Si vous êtes coincé avec un pré 1.5 (ou 5.0) JRE, vous ,peut avoir recours à la sorte de roulement de votre propre, mais vous êtes toujours mieux de par l'utilisation d'un backport: http://backport-jsr166.sourceforge.net/
OriginalL'auteur Jeroen van Bergen