2012-01-16 18 views
35

quanto ne so, java.util.Hashtable sincronizza ogni metodo nell'interfaccia java.util.Map, mentre Collections.synchronizedMap(hash_map) restituisce un oggetto involucro contenente metodi sincronizzati delega chiamate al reale hash_map (correggetemi se ho torto).Differenza tra Hashtable e Collections.synchronizedMap (HashMap)

Ho due domande:

  1. Che differenza fa per sincronizzare ogni metodo e di avere una classe wrapper? Quali sono gli scenari da scegliere l'uno rispetto all'altro?

  2. Cosa succede quando facciamo Collections.synchronizedMap(hash_table)? Sarà uguale semplicemente a un normale java.util.Hashtable?

+0

possibile duplicato di [Differenze tra HashMap e Hashtable?] (Http://stackoverflow.com/questions/40471/differenze-tra -hashmap-and-hashtable) –

+13

Questo non è un duplicato di * quella * domanda. Si tratta di confrontare il wrapper sincronizzato su una HashMap (o HashTable) con un HashTable. –

+0

Sarei interessato a sapere se ci sono differenze nelle prestazioni, che nessuna delle attuali risposte risolve. Chiamare i metodi di un 'Collections.synchronizedMap' tramite una variabile di tipo Map significa che ci sono 2 chiamate virtuali di interfaccia prima di arrivare all'implementazione, mentre con Hashtable c'è almeno 1 chiamata virtuale e si può dichiarare la variabile come tipo Hashtable direttamente, e fallo con 0 chiamate virtuali. Ma forse HashMap differisce in altri modi che lo rendono più veloce nel complesso. – Boann

risposta

13

Ecco le risposte che ho ottenuto da un po 'di (si spera corretta) di ricerca:

  1. Sia fornire lo stesso grado di sincronizzazione. Se dovessi avvolgere Hashtable in Collections.synchronized avresti lo stesso grado, ma con un altro layer ridondante, di sincronizzazione.

  2. La differenza principale tra Hashtable e Collections.synchronizedMap(HashMap) esiste più a livello di API. Poiché Hashtable fa parte del codice legacy di Java, vedrai che l'API Hashtable è stata migliorata per implementare l'interfaccia Map, per diventare parte del framework delle raccolte Java. Ciò significa che se dovessi avvolgere Hashtable tramite Collections.synchronizedMap(), l'API del Hashtable impacchettato si limitasse all'API Map. Quindi, se l'API di Hashtable è inclusa nella definizione del comportamento , allora è ovviamente alterata/limitata.

1

A rischio di affermare l'ovvio (o sbagliare semplice) non è la differenza che

Gli involucri sincronizzazione aggiungono sincronizzazione automatica (thread-sicurezza) ad una raccolta arbitraria

http://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html e continua a dire

Una raccolta creata in questo modo è sicura per thread come una raccolta normalmente sincronizzata , ad esempio un vettore.

È possibile, come per vedere questa discussione per questioni riguardanti HashMaps e concorrenza - Hashmap concurrency issue (o si sono forse molto consapevole di loro già). Un buon esempio è:

Le condizioni che descrivi non saranno soddisfatte da HashMap. Dal il processo di aggiornamento di una mappa non è atomico, è possibile che si verifichi la presenza della mappa in uno stato non valido. Più scritture potrebbero lasciarlo in uno stato corrotto. ConcurrentHashMap (1.5 o successivo) fa quello che vuoi.

https://stackoverflow.com/a/1003071/201648

Credo che in termini di "quando si usa questo" Io tenderebbe a utilizzare la collezione syncronised dove è richiesta concorrenza, altrimenti si può essere la creazione di più lavoro per te stesso (vedi sotto).

In termini di alterare il comportamento

Se viene utilizzato un iteratore esplicito, il metodo iteratore deve essere chiamato dall'interno del blocco sincronizzato. La mancata osservanza di questi consigli può causare un comportamento non deterministico

Ci sono più conseguenze dell'utilizzo di sincronizzazione dato al link (Oracle) in dotazione.

4

La prima classe di raccolta associativa a comparire nella libreria Java era Hashtable, che faceva parte di JDK 1.0. Hashtable forniva una funzionalità mappa associativa facile da usare, thread-safe ed era sicuramente conveniente. Tuttavia, la sicurezza del thread ha avuto un prezzo - tutti i metodi di Hashtable sono stati sincronizzati. A quel tempo, la sincronizzazione senza contesa aveva un costo misurabile delle prestazioni. Il successore di Hashtable, HashMap, che è apparso come parte del framework Collections in JDK 1.2, ha indirizzato la sicurezza del thread fornendo una classe di base non sincronizzata e un wrapper sincronizzato, Collections.synchronizedMap. Separando la funzionalità di base da , le collezioni di sicurezza thread.synchronizedMap consentivano agli utenti che avevano bisogno della sincronizzazione di averlo, ma gli utenti che non ne avevano bisogno non avevano il per pagarlo.

L'approccio semplice alla sincronizzazione prese dal Hashtable e synchronizedMap - sincronizzazione ogni metodo sul Hashtable o dell'oggetto involucro sincronizzato Mappa - ha due difetti principali. È un ostacolo alla scalabilità, perché solo una discussione può accedere alla tabella hash alla volta. Allo stesso tempo, non è sufficiente a fornire una vera sicurezza del thread, in quanto molte operazioni composte comuni richiedono ancora sincronizzazione aggiuntiva. Mentre semplici operazioni come get() e put() possono completare in modo sicuro senza ulteriore sincronizzazione , esistono diverse sequenze di operazioni comuni, come iterazione o put-if-absent, che richiedono comunque la sincronizzazione esterna per evitare le corse di dati .

Il seguente collegamento è fonte e ha più informazioni: Concurrent Collections Classes

+1

Il secondo paragrafo dice che 'Hashtable' e' synchronizedMap' sono la stessa cosa. Il che significa che non abbiamo risposto alla domanda: qual è la loro differenza? – Pacerier

+0

leggi la risposta di @mankadnandan –

3

La differenza non è tanto a livello di API evidente e ci sono molte sottigliezze a livello attuazione. Ad esempio, Hashtable non esegue il ricalcolo avanzato dei codici hash delle chiavi fornite che riduce le collisioni di hash. D'altra parte, Hashtable#hashCode() evita la ricorsione infinita per gli hash autoreferenti per consentire "a certe applet di 1,1 anni con tabelle hash autoreferenziali di funzionare".

In generale, tuttavia, non si deve contare su Hashtable ricevere ulteriori miglioramenti o perfezionamenti oltre alla correttezza di base e alla compatibilità con le versioni precedenti. È considerato una reliquia dal passato profondo di Java.

45

Un'altra differenza che posso trovare alla realizzazione di entrambe le classi è il seguente:

• La classe Hashtable ha tutti i metodi sincronizzati cioè il bloccaggio è fatto a livello di metodo e quindi si può dire che il mutex è sempre allo stato Hashtable oggetto (this).

• Il metodo Collections.synchronizedMap(Map) restituisce un'istanza di SynchronizedMap che è una classe interna della classe Collections. Questa classe ha tutti i suoi metodi in un blocco Synchronized con un mutex. La differenza sta nel mutex qui. La classe interna SynchronizedMap ha due costruttori, uno che accetta solo Map come argomento e un altro che prende uno Map e uno Object (mutex) come argomento. Per impostazione predefinita se si utilizza il primo costruttore di passaggio solo a Map, this viene utilizzato come mutex. Tuttavia, lo sviluppatore è autorizzato a passare un altro oggetto di mutex come secondo argomento con il quale il blocco sui metodi Map sarebbe solo su quello Object e quindi meno restrittivo di Hashtable.

• Quindi, Hashtable utilizza sincronizzazione livello di metodo ma Collections.synchronizedMap(Map) fornisce una flessibilità di blocco sviluppatore fornito mutex con Synchronized blocco.

+2

Che bella risposta, sottolineando ciò che rimane intatto altrimenti nelle risposte di riposo. +1 –

+3

Il costruttore extra e la sincronizzazione a livello di blocco (a differenza del livello di metodo per HashTable) sono le chiavi. –

+3

Questa è un'informazione davvero interessante, ma la classe interna di SynchronizedMap è privata e non esiste un metodo statico corrispondente alla versione del costruttore che accetta un oggetto mutex come argomento, quindi lo sviluppatore non può realmente fornire un mutex personalizzato, giusto? – CarLuva