2010-04-23 20 views
10

Sto provando a creare una LinkedHashMap concorrente per un'architettura con multithreading.Implementazione di una LinkedHashMap simultanea

Se utilizzo Collections#synchronizedMap(), dovrei utilizzare i blocchi sincronizzati per l'iterazione. Questa implementazione porterebbe ad un'aggiunta sequenziale di elementi.

Se utilizzo ConcurrentSkipListMap esiste un modo per implementare uno Comparator da memorizzare in sequenza, come memorizzato in Elenco o coda collegati.

Vorrei utilizzare i pacchetti integrati di java anziché di terze parti.

EDIT:

In questo concomitante LinkedHashMap, se le chiavi sono il nome, desidero mettere le chiavi in ​​sequenza del loro arrivo. Ad esempio, il nuovo valore verrebbe aggiunto all'inizio o alla fine, ma in sequenza.

Durante l'iterazione, è possibile aggiungere LinkedHashMap con nuove voci o rimosso. ma l'iterazione dovrebbe essere la sequenza in cui sono state aggiunte le voci.

Capisco che utilizzando Collections#synchronizedMap(), sarebbe necessario implementare un blocco sincronizzato per l'iterazione, ma la mappa sarebbe modificabile (le voci potrebbero essere aggiunte/rimosse) mentre viene iterata.

+0

Di cosa getter/setter stai parlando? Cosa stai cercando di "memorizzare in sequenza"? Si prega di fornire maggiori dettagli - è difficile capire cosa stai cercando di fare in questo momento. –

+0

Cosa stai cercando di memorizzare in sequenza? Se le tue chiavi hanno un ordine definibile, dovresti essere in grado di scrivere un comparatore. Forse dovresti fornire maggiori informazioni sulle chiavi della tua mappa e su come vorresti ordinarle. –

risposta

1

Utilizzare Collections#synchronizedMap().

Secondo la mia convinzione, se utilizzo Collections.synchronizedMap(), dovrei utilizzare blocchi sincronizzati per getter/setter.

Questo non è vero. È sufficiente sincronizzare l'iterazione su una qualsiasi delle viste (keyset, valori, entryset). Vedi anche la documentazione dell'API obsoleta.

+0

se la mappa viene iterata, quindi sarebbe possibile per gli altri thread aggiungere o rimuovere elementi dalla mappa? – Nilesh

+0

Questa implementazione potrebbe comportare l'aggiunta sequenziale di elementi – Nilesh

+0

1) Non se si sincronizza l'iterazione come da documentazione (avete comunque fatto clic sul collegamento?). Questo è l'intero punto della sincronizzazione. 2) Sì, l'aggiunta è già sincronizzata internamente, è anche il tuo intento, vero? – BalusC

2

Se si utilizza synchronizedMap, non è necessario sincronizzarsi esternamente, tranne che per l'iterazione. Se è necessario conservare l'ordine della mappa, è necessario utilizzare SortedMap. È possibile utilizzare ConcurrentSkipListMap, che è thread-safe, o un'altra SortedMap in combinazione con synchronizedSortedMap.

2

A LinkedHashMap Un elenco doppiamente collegato che scorre in una tabella hash. Un FIFO muta solo i link su una scrittura (inserimento o rimozione). Ciò rende l'implementazione di una versione abbastanza semplice.

  1. Scrivere un LHM con solo l'ordine di inserimento consentito.
  2. Passare a ConcurrentHashMap come tabella hash.
  3. Proteggi/#remove() con un lucchetto.
  4. Rende volatile il campo "successivo".

In iterazione, non è necessario alcun blocco in quanto è possibile seguire in sicurezza il campo "successivo". Le letture possono essere bloccate semplicemente delegando al CHM su un #get().

+0

Senza offesa, ma lo odio quando le persone parlano così. So cosa è una lista doppiamente collegata. So cos'è un hashtable. Ma cosa vuol dire una doppia lista concatenata che attraversa un hashtable? – Pacerier

+1

Sì, è difficile da spiegare e visualizzare. Vedi questa [presentazione] (http://concurrentlinkedhashmap.googlecode.com/files/ConcurrentCachingAtGoogle.pdf) dove ho fatto un tentativo. L'idea è che un elenco collegato mantiene l'ordine e richiede una ricerca O (n). Una tabella hash non è ordinata e trova una voce nel tempo O (1). La combinazione è che la voce della tabella hash contiene i puntatori di elenco in modo che una voce sia ordinata nell'elenco. Le voci nell'elenco possono essere aggiunte (ordine FIFO), spostate in testa/coda (ordine LRU) e rimosse in tempo O (1) (sfratto). Ciò fornisce un inserimento o l'accesso alla mappa ordinata a basso costo. –

+1

non è vero che se ordino il mio 'HashMap', diventerebbe effettivamente una hashmap" ordinata ", che sostanzialmente sconfigge lo scopo di un' LinkedHashMap'? – Pacerier

1

Fino ad ora, il mio progetto ha utilizzato LRUMap da Apache Collections ma è basato su SequencedHashMap. Le raccolte propongono lo ListOrderedMap ma nessuno è sicuro per i thread.

Sono passato a MapMaker da Google Guava. Puoi anche guardare allo CacheBuilder.

0

Quindi, la risposta più semplice sarebbe quella di utilizzare un fornitore di chiavi monotonicamente crescente su cui funziona il vostro Comparator. Pensa allo AtomicInteger e ogni volta che inserisci, crei una nuova chiave da utilizzare per i confronti. Se si raggruppa la propria chiave reale, è possibile creare una mappa interna di OrderedKey<MyRealKeyType>.

class OrderedKey<T> implements Comparable<OrderedKey<T>> { 
    T realKey; 
    int index; 
    OrderedKey(AtomicInteger source, T key) { 
    index = source.getAndIncrement(); 
    realKey = key; 
    } 
    public int compareTo(OrderedKey<T> other) { 
    if (Objects.equals(realKey, other.realKey)) { 
     return 0; 
    } 
    return index - other.index; 
    } 


} 

Ciò ovviare alla necessità di un comparatore personalizzato, e vi darà (1) il metodo per calcolare dimensioni (a meno che non si consente rimuove, nel qual caso, contare quelle pure, in modo da poter semplicemente sottrarre una bella O "tutti i rimossi con successo" da "tutti gli add. riusciti", dove con successo si è effettivamente creata o rimossa una voce).

+0

Fare attenzione alle perdite di memoria; potresti voler aggiungere WeakReference a cose costose ... anche se le cose costose tendono ad essere piuttosto brutte come le chiavi in ​​una mappa, a volte hai solo bisogno di una lista dinamica di tuple (e sei troppo pigro per creare un vero Oggetto per esso), e java manca della sintassi per esprimerlo con grazia. Usando la semantica della mappa attuale, ovviamente, si desidera una mappa ordinata per l'inserimento di dati, che OrderedKey consente per te. – Ajax