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).
fonte
2016-03-13 20:32:49
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. –