Quand préférer LinkedBlockingQueue
plutôt que ArrayBlockingQueue
?
Quelle structure de données utiliser parmi LinkedBlockingQueue
et ArrayBlockingQueue
lorsque:
Bien qu'il y ait une question similaire mais elle ne met pas en évidence le fait que laquelle devrait être préférée?
Liens:
Boris l'araignée a déjà souligné la différence la plus visible entre ArrayBlockingQueue
et LinkedBlockingQueue
- la première est toujours limitée, tandis que la seconde peut être illimitée.
Donc, si vous avez besoin d'une file d'attente de blocage illimitée, LinkedBlockingQueue
ou LinkedTransferQueue
utilisé comme BlockingQueue
sont vos meilleurs paris de la Java.util.concurrent
boîte à outils.
Mais disons que vous avez besoin d'une file d'attente de blocage bornée. En fin de compte, vous devez choisir une implémentation basée sur une expérimentation approfondie avec une simulation de votre charge de travail réelle. Néanmoins, voici quelques notes qui peuvent vous aider dans votre choix ou dans l'interprétation des résultats de l'expérience:
ArrayBlockingQueue
peut être créé avec une politique d'équité de planification configurable (marche/arrêt). C'est génial si vous avez besoin d'équité ou si vous voulez éviter la famine des producteurs/consommateurs, mais cela vous coûtera en débit.ArrayBlockingQueue
pré-alloue son tableau de sauvegarde, donc il n'alloue pas de nœuds lors de son utilisation, mais il prend immédiatement ce qui peut être un morceau de mémoire considérable, ce qui peut être un problème si votre mémoire est fragmentée.ArrayBlockingQueue
devrait avoir moins de variabilité dans les performances, car il a globalement moins de pièces mobiles, il utilise un algorithme de verrouillage unique plus simple et moins sophistiqué, il ne crée pas de nœuds pendant l'utilisation et son comportement de cache doit être assez cohérent .LinkedBlockingQueue
devrait avoir un meilleur débit, car il utilise des verrous séparés pour la tête et la queue.LinkedBlockingQueue
ne pré-alloue pas de nœuds, ce qui signifie que son empreinte mémoire correspondra à peu près à sa taille, mais cela signifie également qu'il faudra un certain travail pour l'allocation et la libération des nœuds.LinkedBlockingQueue
aura probablement un comportement de cache pire, ce qui peut affecter ses propres performances, mais aussi les performances d'autres composants en raison d'un faux partage.En fonction de votre cas d'utilisation et de l'importance que vous accordez aux performances, vous pouvez également regarder en dehors de Java.util.concurrent
et considérez Disruptor (un tampon d'anneau non bloquant borné exceptionnellement rapide mais quelque peu spécialisé) ou JCTools (une variété de files d'attente bornées ou non bornées avec des garanties différentes selon la nombre de producteurs et de consommateurs).
Depuis JavaDoc pour ArrayBlockingQueue
Une file d'attente de blocage bornée soutenue par un tableau.
Emphase mine
Depuis JavaDoc pour LinkedBlockingQueue
:
Une file d'attente de blocage éventuellement limitée basée sur les nœuds liés.
Emphase mine
Donc, si vous avez besoin d'une file d'attente bornée , vous pouvez utiliser l'une ou l'autre, si vous avez besoin d'une illimitée file d'attente, vous devez utiliser LinkedBlockingQueue
.
Pour une file d'attente bornée , vous devrez alors effectuer un benchmark pour déterminer ce qui est le mieux.