Je crée une application Java avec un thread d'application logique et un thread d'accès à la base de données. Les deux persistent pendant toute la durée de vie de l'application et doivent tous deux être exécutés en même temps (l'un parle au serveur, l'autre à l'utilisateur; lorsque l'application est complètement démarrée, j'ai besoin des deux pour fonctionner).
Cependant, au démarrage, je dois m'assurer qu'au départ, le thread d'application attend que le thread db soit prêt (actuellement déterminé en interrogeant une méthode personnalisée dbthread.isReady()
). Cela ne me dérangerait pas si le thread d'application se bloque jusqu'à ce que le thread db soit prêt.
Thread.join()
ne ressemble pas à une solution - le thread db se termine uniquement à l'arrêt de l'application.
while (!dbthread.isReady()) {}
fonctionne, mais la boucle vide consomme beaucoup de cycles de processeur.
D'autres idées? Merci.
la source
a
attend un objet,synchronised(object)
comment un autre thread peut-il passersynchronized(object)
pour appeler leobject.notifyAll()
? Dans mon programme, tout est resté bloqué sur dessynchronozed
blocs.object.wait()
le déverrouillage efficace du verrou sur cet objet. Lorsque le deuxième thread "quitte" son bloc synchronisé, les autres objets sont libérés de lawait
méthode et obtiennent à nouveau le verrou à ce stade.Utilisez un CountDownLatch avec un compteur de 1.
Maintenant, dans le fil de l'application, faites-
Dans le fil db, une fois que vous avez terminé, faites -
la source
countDown()
enfinally{}
blocExigence ::
Répondre ::
Travail accompli!! Voir l'exemple ci-dessous
Sortie de ce programme:
Vous pouvez voir que cela prend 6 secondes avant de terminer sa tâche qui est supérieure à celle des autres threads. Donc Future.get () attend que la tâche soit terminée.
Si vous n'utilisez pas future.get (), il n'attend pas pour terminer et exécute la consommation de temps basée.
Bonne chance avec la concurrence Java.
la source
CountdownLatch
es, mais la vôtre est une approche beaucoup plus flexible.Beaucoup de réponses correctes mais sans exemple simple. Voici un moyen simple et facile à utiliser
CountDownLatch
:la source
Utilisez cette classe comme ceci alors:
Créez un ThreadEvent:
Dans la méthode, cela attend des résultats:
Et dans la méthode qui crée les résultats une fois que tous les résultats ont été créés:
ÉDITER:
(Désolé d'avoir édité ce post, mais ce code a une très mauvaise condition de course et je n'ai pas assez de réputation pour commenter)
Vous ne pouvez l'utiliser que si vous êtes sûr à 100% que signal () est appelé après await (). C'est la seule grande raison pour laquelle vous ne pouvez pas utiliser d'objet Java comme par exemple les événements Windows.
Si le code s'exécute dans cet ordre:
alors le fil 2 attendra indéfiniment . En effet, Object.notify () ne réveille qu'un des threads en cours d'exécution. Un thread qui attend plus tard n'est pas réveillé. Ceci est très différent de la façon dont je m'attends à ce que les événements fonctionnent, où un événement est signalé jusqu'à ce que a) attendu ou b) explicitement réinitialisé.
Remarque: la plupart du temps, vous devez utiliser notifyAll (), mais cela n'est pas pertinent pour le problème "attendre pour toujours" ci-dessus.
la source
Essayez la classe CountDownLatch hors du
java.util.concurrent
package, qui fournit des mécanismes de synchronisation de plus haut niveau, qui sont beaucoup moins sujets aux erreurs que n'importe lequel des éléments de bas niveau.la source
Vous pouvez le faire en utilisant un objet Exchanger partagé entre les deux threads:
Et dans le deuxième fil:
Comme d'autres l'ont dit, ne prenez pas ce code léger et copiez-collez simplement. Lisez d'abord.
la source
L' interface Future du
java.lang.concurrent
package est conçue pour donner accès aux résultats calculés dans un autre thread.Jetez un œil à FutureTask et ExecutorService pour une manière toute faite de faire ce genre de chose.
Je recommande vivement de lire Java Concurrency In Practice à toute personne intéressée par la concurrence et le multithreading. Il se concentre évidemment sur Java, mais il y a beaucoup de viande pour quiconque travaille dans d'autres langues aussi.
la source
Si vous voulez quelque chose de rapide et de sale, vous pouvez simplement ajouter un appel Thread.sleep () dans votre boucle while. Si la bibliothèque de base de données est quelque chose que vous ne pouvez pas changer, il n'y a vraiment pas d'autre solution simple. L'interrogation de la base de données jusqu'à ce qu'elle soit prête avec une période d'attente ne tuera pas les performances.
Presque quelque chose que vous pourriez appeler un code élégant, mais qui fait le travail.
Dans le cas où vous pouvez modifier le code de la base de données, il est préférable d'utiliser un mutex comme proposé dans d'autres réponses.
la source
Ceci s'applique à toutes les langues:
Vous voulez avoir un modèle événement / écouteur. Vous créez un écouteur pour attendre un événement particulier. L'événement serait créé (ou signalé) dans votre thread de travail. Cela bloquera le thread jusqu'à ce que le signal soit reçu au lieu d'interroger constamment pour voir si une condition est remplie, comme la solution que vous avez actuellement.
Votre situation est l'une des causes les plus courantes de blocages - assurez-vous de signaler l'autre thread quelles que soient les erreurs qui se sont produites. Exemple - si votre application lève une exception - et n'appelle jamais la méthode pour signaler à l'autre que les choses sont terminées. Cela fera en sorte que l'autre thread ne se «réveille» jamais.
Je vous suggère de vous pencher sur les concepts d'utilisation d'événements et de gestionnaires d'événements pour mieux comprendre ce paradigme avant de mettre en œuvre votre cas.
Vous pouvez également utiliser un appel de fonction de blocage en utilisant un mutex, ce qui fera attendre le thread pour que la ressource soit libre. Pour ce faire, vous avez besoin d'une bonne synchronisation des threads, par exemple:
la source
Vous pouvez lire à partir d'une file d'attente de blocage dans un thread et y écrire dans un autre thread.
la source
Puisque
join()
a été excluVous pouvez envisager d'autres alternatives:
invokeAll de
ExecutorService
ForkJoinPool ou newWorkStealingPool de
Executors
(depuis la version Java 8)la source
Cette idée peut s'appliquer ?. Si vous utilisez CountdownLatches ou Semaphores fonctionne parfaitement, mais si vous cherchez la réponse la plus simple pour une interview, je pense que cela peut s'appliquer.
la source