2016-03-13 8 views
10

Quando preferire LinkedBlockingQueue su ArrayBlockingQueue?Quando preferire LinkedBlockingQueue su ArrayBlockingQueue?

Quale struttura di dati da utilizzare tra LinkedBlockingQueue e ArrayBlockingQueue quando:

  1. Si desidera una lettura efficace e scrittura
  2. dovrebbe avere impronte di memoria minore

Anche se v'è una domanda simile, ma non evidenzia il fatto che dovrebbe essere preferito?

vicini:

risposta

18

Boris the Spider ha già delineato la differenza più visibile tra ArrayBlockingQueue e LinkedBlockingQueue - il primo è sempre limitato, mentre il secondo può essere illimitato.

Quindi, nel caso in cui avete bisogno di una coda di blocco illimitata, LinkedBlockingQueue o un LinkedTransferQueue utilizzato come BlockingQueue sono i tuoi migliori scommesse dal java.util.concurrent Toolbox.

Ma supponiamo che sia necessaria una coda di blocco limitata. Alla fine, dovresti scegliere un'implementazione basata su un'ampia sperimentazione con una simulazione del carico di lavoro del mondo reale. Tuttavia, qui alcune note che possono aiutare con la vostra scelta o con l'interpretazione dei risultati della sperimentazione:

  • ArrayBlockingQueue può essere creato con un configurabile (on/off) la politica di pianificazione equità. Questo è ottimo se hai bisogno di equità o vuoi evitare la fame da parte del produttore/consumatore, ma ti costerà il throughput.
  • ArrayBlockingQueue pre-alloca il proprio backing array, quindi non alloca i nodi durante l'utilizzo, ma prende immediatamente quello che può essere un considerevole frammento di memoria, che può essere un problema se la memoria è frammentata.
  • ArrayBlockingQueue dovrebbe avere una minore variabilità delle prestazioni, poiché ha meno parti mobili in generale, utilizza un algoritmo single-lock più semplice e meno sofisticato, non crea nodi durante l'uso e il suo comportamento della cache dovrebbe essere abbastanza coerente.
  • LinkedBlockingQueue dovrebbe avere un rendimento migliore, perché utilizza blocchi separati per la testa e la coda.
  • LinkedBlockingQueue non pre-alloca i nodi, il che significa che il suo ingombro di memoria corrisponderà grosso modo alle sue dimensioni, ma significa anche che dovrà sostenere alcuni lavori per l'allocazione e la liberazione dei nodi.
  • LinkedBlockingQueue probabilmente avrà un comportamento di cache peggiore, che potrebbe influire sulle proprie prestazioni, ma anche sulle prestazioni di altri componenti a causa della condivisione errata.

A seconda del caso d'uso e quanto si fa a cura di prestazioni, si potrebbe anche voler guardare al di fuori di java.util.concurrent e considerare Disruptor (un non-blocking buffer circolare eccezionalmente veloce, ma un po 'specializzato limitato) o JCTools (una varietà di code limitate o illimitate con garanzie diverse a seconda del numero di produttori e consumatori).

+0

Bella risposta! Sono d'accordo con ciò che hai menzionato anche vorrei sottolineare (di nuovo) il fatto che ArrayBlockingQueue è supportato da un array la cui dimensione non cambierà mai dopo la creazione. Impostare la capacità su Integer.MAX_VALUE creerebbe un grande array con costi elevati nello spazio. ArrayBlockingQueue è sempre limitato. LinkedBlockingQueue crea i nodi dinamicamente fino al raggiungimento della capacità. Questo è di default Integer.MAX_VALUE. L'utilizzo di una capacità così grande non ha costi aggiuntivi nello spazio. LinkedBlockingQueue è facoltativamente limitato. –

-1

Entrambi di loro implementano BlockingQueue. Come suggerisce il nome, arrayBlockingQueue è supportato da Array mentre LinkedBlockingQueue è supportato da un linked list.

Quale scegliere dovrebbe essere essenzialmente lo stesso come il motivo di scegliere tra un ArrayList e LinkedList

Aggiunta di un elemento di ArrayBlockingQueue si suppone essere più veloce poiché significa solamente impostando un riferimento a un elemento del supporto La matrice di oggetti, mentre si aggiunge un elemento a LinkedBlockingQueue significa creare un Node e impostare i suoi elementi, prev e next campi. Inoltre, quando rimuoviamo un elemento da LinkedBlockingQueue il Nodo rimosso diventa spazzatura che può influenzare le prestazioni dell'app.

+0

Questa è solo una risposta parziale, la differenza principale è che 'ArrayBlockingQueue' è associato a un array ** di dimensione fissa ** (utilizzando un'implementazione di array circolare). –

+0

@BoristheSpider, controlla il ragionamento aggiuntivo. Oltre al punto specificato nella risposta, i BlockingQueues hanno le stesse implicazioni delle strutture di dati sottostanti – Rahul

+0

La struttura di blocco delle due code è completamente diversa. Confrontare la loro struttura interna è alquanto irrilevante; avresti bisogno di vedere quale struttura di blocco si confronta meglio nel tuo particolare ambiente multithreaded: uno scrittore/molti lettori, molti scrittori/un lettore ecc. ecc. –

5

Dal JavaDoc for ArrayBlockingQueue

Un delimitata blocco coda sostenuta da un array.

enfasi è mia

Dal JavaDoc for LinkedBlockingQueue:

Un opzionalmente-delimitata blocco coda sulla base di nodi collegati.

enfasi è mia

Quindi, se avete bisogno di un delimitata coda è possibile utilizzare, se avete bisogno di una coda illimitata è necessario utilizzare LinkedBlockingQueue.

Per una limitata a coda, quindi è necessario eseguire un benchmark per capire quale è meglio.

+0

Per essere in grado di dichiarare una coda illimitata è anche uno dei motivi specificati nella mia risposta come linkedList è illimitato mentre gli array no. – Rahul

+0

@rahulroc in realtà non lo dici mai e non fornisci mai alcuna prova per le tue asserzioni. Dire che una serie di array backed è limitata è anche semplicistica e non vera - un 'ArrayList' è supportato da array. –

+0

Grazie per la tua risposta @BoristheSpider. Hai ragione, questa è una buona ragione per preferire, ma abbiamo delle differenze nelle prestazioni quando: 1.Volete una lettura e scrittura efficienti 2. non vi è alcuna preoccupazione sul fatto che la coda sia o meno limitata 3. dovrebbe avere un footprint di memoria inferiore? –

Problemi correlati