2013-06-12 10 views
17

Penso che, nella maggior parte dei casi, lo ArrayBlockingQueue funzionerà meglio dello LinkedBlockingQueue. Tuttavia, questo è il caso quando c'è sempre abbastanza spazio nell'array ... Se si riempie, non è molto prevedibile se andrà altrettanto bene, poiché bloccherà il thread che sta cercando di spingere i dati nella coda ..Java: ArrayBlockingQueue vs. LinkedBlockingQueue

Quindi, la mia domanda è: Esiste un'implementazione di middle-ground di BlockingQueue? Supponiamo, uno ArrayListBlockingQueue o uno BucketListBlockingQueue? Qualcosa come un elenco di matrici, in modo che la coda possa aumentare in modo dinamico la capacità, pur avendo ancora un vantaggio ragionevole dall'utilizzo di array per archiviare i dati in modo definitivo?

+0

Un elenco di matrici non darebbe un miglioramento delle prestazioni ... Perché dovrebbe? E inoltre: perché sei preoccupato per le prestazioni? Hai avuto davvero problemi? Hai profilo? – Dariusz

+0

Sto pensando alla località di memoria. Se si utilizza un elenco collegato i cui elementi saltano attorno a indirizzi di memoria casuali, è molto più probabile che si verifichino problemi di cache e problemi del genere.Inoltre, per recuperare dalla memoria, devi recuperare l'indirizzo dell'elemento successivo, e quindi recuperare il contenuto di tale indirizzo ... Considerando che, con un array, devi solo fare indirizzo ++ per ottenere l'indirizzo dell'elemento successivo. Con un elenco di matrici, avresti qualche compromesso tra le due implementazioni ... Pensi diversamente? –

+1

Penso che un elenco di matrici ti dia vantaggi da nessuna delle raccolte originali. Devi ancora allocare memoria e, a seconda della dimensione degli array, diventerà più o meno frammentato. Penso che se realizzi correttamente il tuo algoritmo di ridimensionamento delle raccolte basato su array, avrai poche ridimensionazioni e una iterazione molto veloce. Per quanto riguarda la località di memoria - le collezioni memorizzano i riferimenti agli oggetti e quegli stessi oggetti possono trovarsi in qualsiasi punto della memoria, quindi non si otterrà alcun guadagno in tal senso dall'uso di una collezione o di un'altra. – Dariusz

risposta

6

I miei 2 centesimi:

Per cominciare, la linea di fondo è che non si interessa davvero la differenza qui perché anche quando si utilizza un LinkedBlockingQueue pianura, la prestazione è abbastanza buono quando si consegnano alcuni sistemi di micro-secondo livello. Quindi la differenza di prestazioni qui non è poi così bella.

Se si sta scrivendo un sistema ad alte prestazioni mission-critical e si utilizzano code per passare messaggi tra thread, è sempre possibile stimare la dimensione della coda necessaria per [Dimensione coda] = [Ritardo massimo accettabile] * [Velocità messaggio massima ]. Tutto ciò che può crescere oltre tale capacità significa che soffri di un problema di consumo lento. In un'applicazione mission critical, tale ritardo indica che il sistema non funziona correttamente. Potrebbe essere necessario qualche processo manuale per assicurarsi che il sistema funzioni correttamente.

Nel caso in cui il sistema non sia di importanza critica, è sufficiente sospendere (bloccare) l'editore fino a quando alcuni utenti non sono disponibili.

14

1. LinkedBlockingQueue (LinkedList Attuazione ma non esattamente JDK Attuazione LinkedList Esso utilizza statica classe interna Nodo per mantenere i collegamenti tra gli elementi) di classe

Constructor for LinkedBlockingQueue 
public LinkedBlockingQueue(int capacity) 
{ 
     if (capacity < = 0) throw new IllegalArgumentException(); 
     this.capacity = capacity; 
     last = head = new Node<E>(null); // Maintains a underlying linkedlist. (Use when size is not known) 
} 

nodo utilizzato per mantenere i collegamenti

static class Node<E> { 
    E item; 
    Node<E> next; 
    Node(E x) { item = x; } 
} 

2. ArrayBlockingQueue (Array Attuazione)

costruzione per ArrayBlockingQueue

public ArrayBlockingQueue(int capacity, boolean fair) 
{ 
      if (capacity < = 0) 
       throw new IllegalArgumentException(); 
      this.items = new Object[capacity]; // Maintains a underlying array 
      lock = new ReentrantLock(fair); 
      notEmpty = lock.newCondition(); 
      notFull = lock.newCondition(); 
} 

IMHO più grande differenza tra ArrayBlockingQueue e LinkedBlockingQueue risulta dal costruttore si ha sottostante array e altri LinkedList.

ArrayBlockingQueue utilizza single-lock double condition algorithm e LinkedBlockingQueue è variante dell'algoritmo "due serratura coda" e ha 2 chiusure 2 condizioni (takeLock, putLock)

Finora diedi confronto tra questi 2 implementazioni Tornando alla domanda iniziale, Una domanda simile è stata posta nel concurrency mailing list in questo doug Lea parla di DynamicArrayBlockingQueue che è implementation provided by Dawid Kurzyniec.

+6

Qui vedo un downvote qui Se non sei d'accordo con la risposta, ti preghiamo di fornire anche i commenti in modo che io possa migliorare o correggere se qualcosa non va. – Vipin

+0

per essere più chiaro 'ArrayBlockingQueue' utilizza' Circular Array' come struttura sottostante +1 per risposta –

Problemi correlati