Comment bloquer jusqu'à ce qu'un BlockingQueue soit vide?
Je suis à la recherche d'un moyen de bloquer jusqu'à ce qu'un BlockingQueue
est vide.
Je sais que, dans un environnement multithread, tant qu'il existe des producteurs à mettre des objets dans la BlockingQueue
il peut y avoir des situations dans lesquelles la file d'attente est vide et quelques nanosecondes plus tard, il est plein d'éléments.
Mais, si il n'y a qu' un producteur, alors il peut attendre (et le bloc) jusqu'à ce que la file d'attente est vide après qu'il a cessé de mettre des éléments dans la file d'attente.
Java/Pseudo:
//Producer code
BlockingQueue queue = new BlockingQueue();
while (having some tasks to do) {
queue.put(task);
}
queue.waitUntilEmpty(); //<-- how to do this?
print("Done");
Avez-vous une idée?
MODIFIER: je sais que l'emballage BlockingQueue
et à l'aide d'une condition supplémentaire ferait l'affaire, je demande juste si il y a quelques pré-solutions et/ou de meilleures alternatives.
source d'informationauteur gd1 | 2013-03-03
Vous devez vous connecter pour publier un commentaire.
Une solution simple à l'aide de
wait()
etnotify()
:- Je comprendre que vous pourriez déjà avoir des tas de fils activement scrutin ou de prendre la file d'attente mais je me sens encore pas tout à fait raison au sujet de votre flux/design.
La file d'attente est vide ne signifie pas déjà ajouté des tâches sont terminées, certains des articles ont pu prendre âges de processus, de sorte qu'il n'est pas trop utile pour vérifier vide.
Donc ce que vous devez faire est d'oublier le
BlockingQueue
vous pouvez l'utiliser comme toutes les autres collections. Traduire les éléments dans uneCollections
deCallable
et de faire usage de laExecutorService.invokeAll()
.Cette approche permettra de vous donner le plein contrôle de combien de temps votre producteur pouvait attendre et la bonne gestion des exceptions.
Ce n'est pas tout à fait ce que vous voulez faire, mais à l'aide d'un
SynchronousQueue
aurait un effet très semblable que votre Java/Pseudo-code, à savoir le producteur de blocage jusqu'à ce que toutes les données ont été récupérées par certains consommateurs.Seule différence étant le producteur de blocage sur chaque mettre jusqu'à ce qu'un consommateur s'agit de récupérer les données, au lieu d'une seule fois à la fin. Vous ne savez pas si cela ferait une différence dans votre cas. Je m'attends qu'à faire une différence notable, si la tâche effectuée par le producteur est un peu cher.
Votre cas d'utilisation doit être assez spécial parce que le plus souvent vous ne souhaitez bloquer le producteur lorsque la file d'attente est pleine, mais ne pas attendre jusqu'à ce qu'elle est vide.
De toute façon, c'est faisable. Je crois que l'essorage jusqu'à
isEmpty
retourne true n'est pas inefficace, parce que le producteur sera localement la filature, c'est à dire, accède à son propre cache, ne pas cogner le bus. Il sera cependant consommer du temps CPU que le fil reste préférence d'heure. Mais les locaux de la filature est certainement le moyen le plus facile. Sinon je vois deux options:wait
+notify
comme @niculare suggéré