E 'possibile avere più di 32 blocchi nel ConcurrentHashMap
-
21-09-2019 - |
Domanda
Ho letto ConcurrentHashMap funziona meglio in multi threading di Hashtable a causa di avere le serrature a livello secchio piuttosto che mappare blocco di larghezza. E 'al massimo 32 serrature possibile per mappa. Volete sapere perché 32 e perché non più di 32 blocchi.
Soluzione
Se si sta parlando del ConcurrentHashMap
Java, allora il limite è arbitraria :
Crea una nuova mappa con le stesse mappature come la mappa dato. La mappa viene creata con una capacità di 1,5 volte il numero di mapping nella mappa dato o 16 (il valore maggiore), e un fattore di carico di default (0,75) e concurrencyLevel (16).
Se leggete la codice sorgente diventa chiaro che il numero massimo di segmenti è 2 ^ 16, che dovrebbe essere più che sufficiente per qualsiasi esigenza concepibile nell'immediato futuro.
Si può avere pensato di alcune implementazioni sperimentali alternativi, come questa :
Questa classe supporta un livello preimpostato concorrenza cablata di 32. Questo consente un massimo di 32 put e / o rimuovere operazioni procedere contemporaneamente.
Si noti che, in generale, fattori diversi efficienza sincronizzazione sono di solito strozzature quando più di 32 fili stanno cercando di aggiornare un singolo ConcurrentHashMap
.
Altri suggerimenti
Il default non è 32, è 16. E si può sovrascrivere con il argomento del costruttore concurrency level
:
public ConcurrentHashMap(int initialCapacity,
float loadFactor,
int concurrencyLevel)
in modo da poter fare:
Map<String, String> map = new ConcurrentHashmap<String, String)(128, 0.75f, 64);
per cambiare a 64. Le impostazioni predefinite sono (come di Java 6u17):
-
initialCapacity
: 16; -
loadFactory
: 0.75f; -
concurrencyLevel
:. 16
Secondo la fonte della ConcurrentHashMap
, il massimo consentito è 65536
:
/**
* The maximum number of segments to allow; used to bound
* constructor arguments.
*/
static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel) {
if (concurrencyLevel > MAX_SEGMENTS)
concurrencyLevel = MAX_SEGMENTS;
Per usare tutto il livello di concorrenza predefinito di 16 è necessario avere 16 core utilizzando la mappa nello stesso momento. Se si dispone di 32 core solo utilizzando la mappa 25% del tempo di allora solo 8 dei 16 segmenti saranno utilizzati in una sola volta.
In sintesi, è necessario disporre di un sacco di nuclei tutti utilizzando la stessa mappa e non fare niente molto altro. veri e propri programmi di solito fanno qualcosa di diverso accesso con un solo programma.