web-dev-qa-db-fra.com

Quand préférer LinkedBlockingQueue à ArrayBlockingQueue?

Quand préférer LinkedBlockingQueue plutôt que ArrayBlockingQueue?

Quelle structure de données utiliser parmi LinkedBlockingQueue et ArrayBlockingQueue lorsque:

  1. Vous voulez une lecture et une écriture efficaces
  2. devrait avoir des empreintes de mémoire moindres

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:

37
Vaibhav Gupta

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).

51
Dimitar Dimitrov

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.

11
Boris the Spider