Qual è la differenza tra l'utilizzo della classe wrapper SynchronizedMap
, su a HashMap
e ConcurrentHashMap
?
È solo in grado di modificarlo HashMap
mentre lo ripetono ( ConcurrentHashMap
)?
Qual è la differenza tra l'utilizzo della classe wrapper SynchronizedMap
, su a HashMap
e ConcurrentHashMap
?
È solo in grado di modificarlo HashMap
mentre lo ripetono ( ConcurrentHashMap
)?
Risposte:
Sincronizzato HashMap
:
Ogni metodo è sincronizzato usando un blocco a livello di oggetto. Quindi i metodi get e put su synchMap acquisiscono un blocco.
Il blocco dell'intera raccolta è un sovraccarico di prestazioni. Mentre un thread mantiene il blocco, nessun altro thread può utilizzare la raccolta.
ConcurrentHashMap
è stato introdotto in JDK 5.
Non esiste alcun blocco a livello di oggetto, il blocco ha una granularità molto più fine. Per a ConcurrentHashMap
, i blocchi potrebbero essere a livello di bucket hashmap.
L'effetto del blocco di livello inferiore è che è possibile avere lettori e scrittori simultanei che non è possibile per le raccolte sincronizzate. Ciò porta a una maggiore scalabilità.
ConcurrentHashMap
non genera un ConcurrentModificationException
se un thread tenta di modificarlo mentre un altro sta iterando su di esso.
Questo articolo Java 7: HashMap vs ConcurrentHashMap è un'ottima lettura. Altamente raccomandato.
ConcurrentHashMap
il size()
risultato potrebbe non essere aggiornato. size()
è consentito restituire un'approssimazione invece di un conteggio esatto secondo il libro "Concorrenza nella pratica Java". Quindi questo metodo dovrebbe essere usato con attenzione.
La breve risposta:
Entrambe le mappe sono implementazioni thread-safe Map
dell'interfaccia. ConcurrentHashMap
è implementato per un throughput più elevato nei casi in cui è prevista un'elevata concorrenza.
L' articolo di Brian Goetz sull'idea alla base ConcurrentHashMap
è un'ottima lettura. Altamente raccomandato.
Map m = Collections.synchronizedMap(new HashMap(...));
docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
ConcurrentHashMap
è thread-safe senza sincronizzare l'intera mappa. Le letture possono avvenire molto velocemente mentre la scrittura viene eseguita con un lucchetto.
Siamo in grado di raggiungere la sicurezza dei thread utilizzando sia ConcurrentHashMap che synchronisedHashmap. Ma c'è molta differenza se guardi alla loro architettura.
Manterrà il blocco a livello di oggetto. Quindi, se si desidera eseguire qualsiasi operazione come put / get, è necessario prima acquisire il blocco. Allo stesso tempo, ad altri thread non è consentito eseguire alcuna operazione. Quindi alla volta, solo un thread può operare su questo. Quindi il tempo di attesa aumenterà qui. Possiamo dire che le prestazioni sono relativamente basse quando si confronta con ConcurrentHashMap.
Manterrà il blocco a livello di segmento. Ha 16 segmenti e mantiene il livello di concorrenza come 16 per impostazione predefinita. Quindi, alla volta, 16 thread possono essere in grado di operare su ConcurrentHashMap. Inoltre, l'operazione di lettura non richiede un blocco. Quindi qualsiasi numero di thread può eseguire un'operazione get su di esso.
Se thread1 vuole eseguire un'operazione put nel segmento 2 e thread2 vuole eseguire un'operazione put sul segmento 4, è consentito qui. Significa che 16 thread possono eseguire operazioni di aggiornamento (put / delete) su ConcurrentHashMap alla volta.
In modo che il tempo di attesa sarà meno qui. Quindi le prestazioni sono relativamente migliori di synchronizedHashmap.
Entrambe sono versioni sincronizzate di HashMap, con differenze nella funzionalità principale e nella struttura interna.
ConcurrentHashMap è costituito da segmenti interni che possono essere visualizzati concettualmente come HashMap indipendenti. Tutti questi segmenti possono essere bloccati da thread separati in esecuzioni simultanee elevate. Pertanto, più thread possono ottenere / inserire coppie chiave-valore da ConcurrentHashMap senza bloccarsi / aspettarsi a vicenda. Questo è implementato per un throughput più elevato.
mentre
Collections.synchronizedMap () , otteniamo una versione sincronizzata di HashMap e vi si accede in modo bloccante. Ciò significa che se più thread tentano di accedere a sincronizedMap allo stesso tempo, saranno autorizzati a ottenere / mettere coppie chiave-valore una alla volta in modo sincronizzato.
ConcurrentHashMap
utilizza un meccanismo di blocco a grana fine noto lock stripping
per consentire un maggiore grado di accesso condiviso. Per questo motivo fornisce una migliore concorrenza e scalabilità .
Anche gli iteratori restituiti ConcurrentHashMap
sono debolmente coerenti invece della tecnica fail fail utilizzata da Synchronized HashMap.
I metodi su SynchronizedMap
trattengono il blocco sull'oggetto, mentre in ConcurrentHashMap
c'è un concetto di "blocco dei blocchi" in cui invece i blocchi vengono mantenuti su secchi del contenuto. Così migliorata scalabilità e prestazioni.
ConcurrentHashMap:
1) Entrambe le mappe sono implementazioni thread-safe dell'interfaccia Mappa.
2) ConcurrentHashMap è implementato per un throughput più elevato nei casi in cui è prevista un'alta concorrenza.
3) Non è presente alcun blocco a livello di oggetto.
Mappa hash sincronizzata:
1) Ogni metodo è sincronizzato usando un blocco a livello di oggetto.
ConcurrentHashMap consente l'accesso simultaneo ai dati. L'intera mappa è divisa in segmenti.
Operazione di lettura, ad es. get(Object key)
non è sincronizzato nemmeno a livello di segmento.
Ma scrivere operazioni cioè. remove(Object key), get(Object key)
acquisire il blocco a livello di segmento. Solo una parte dell'intera mappa è bloccata, altri thread possono ancora leggere valori da vari segmenti tranne uno bloccato.
SynchronizedMap, d'altra parte, acquisisce il blocco a livello di oggetto. Tutti i thread devono attendere il thread corrente indipendentemente dall'operazione (lettura / scrittura).
Un semplice test delle prestazioni per ConcurrentHashMap vs Synchronized HashMap
. Il flusso di test sta chiamando put
in un thread e chiama contemporaneamente get
in tre thread Map
. Come diceva @trshiv, ConcurrentHashMap ha un throughput e una velocità maggiori per le cui operazioni di lettura senza blocco. Il risultato è al termine dei tempi di funzionamento 10^7
, ConcurrentHashMap è 2x
più veloce di Synchronized HashMap.
SynchronizedMap
e ConcurrentHashMap
sono entrambi classe thread-safe e possono essere utilizzati in applicazioni multithread, la principale differenza tra loro è relativa al modo in cui ottengono la sicurezza del thread.
SynchronizedMap
acquisisce il blocco sull'intera istanza di Map, mentre ConcurrentHashMap
divide l'istanza di Map in più segmenti e il blocco viene eseguito su quelli.
Come da java doc
Hashtable e Collections.synchronizedMap (new HashMap ()) sono sincronizzati. Ma ConcurrentHashMap è "concorrente".
Una raccolta simultanea è thread-safe, ma non governata da un singolo blocco di esclusione.
Nel caso particolare di ConcurrentHashMap, consente in modo sicuro qualsiasi numero di letture simultanee nonché un numero sintonizzabile di scritture simultanee. Le classi "sincronizzate" possono essere utili quando è necessario impedire qualsiasi accesso a una raccolta tramite un singolo blocco, a scapito di una minore scalabilità.
In altri casi in cui ci si aspetta che più thread accedano a una raccolta comune, sono normalmente preferibili versioni "concorrenti". E le raccolte non sincronizzate sono preferibili quando entrambe le raccolte sono non condivise o sono accessibili solo quando si tengono altri blocchi.
Hashtable
eSynchronized HashMap
?