Die Verwendung von ConcurrentHashMap
wird für große Maps oder eine große Anzahl von Lese-Schreiboperationen empfohlen aufgrund von:
- Beim Lesen aus der Map wird sie nicht gesperrt. Wenn also 5 Threads daraus lesen, können alle gleichzeitig aus der Map lesen.
- Beim Schreiben wird nur der relevante Datensatz (Schlüssel) gesperrt. Wenn also 5 Threads Werte unterschiedlicher Schlüssel schreiben, können all diese Operationen gleichzeitig durchgeführt werden. Wenn jedoch 2 Threads denselben Schlüssel schreiben, sind diese Operationen thread-sicher. Das liegt daran, dass es keine Sperrung auf Objektebene (Map) gibt, sondern auf einer viel feineren Granularität - auf Ebene des Hashmap-Buckets.
Betrachten Sie das folgende Beispiel:
public class ConcurrentHashMapExample {
public static void main(String[] args) {
//ConcurrentHashMap
Map myMap = new ConcurrentHashMap();
myMap.put("1", "1");
myMap.put("2", "1");
myMap.put("3", "1");
myMap.put("4", "1");
myMap.put("5", "1");
myMap.put("6", "1");
System.out.println("ConcurrentHashMap vor Iterator: "+myMap);
Iterator itr1 = myMap.keySet().iterator();
while(itr1.hasNext()){
String key = itr1.next();
if(key.equals("3")) myMap.put(key+"new", "new3");
}
System.out.println("ConcurrentHashMap nach Iterator: "+myMap);
//HashMap
myMap = new HashMap();
myMap.put("1", "1");
myMap.put("2", "1");
myMap.put("3", "1");
myMap.put("4", "1");
myMap.put("5", "1");
myMap.put("6", "1");
System.out.println("HashMap vor Iterator: "+myMap);
Iterator itr2 = myMap.keySet().iterator();
while(itr2.hasNext()){
String key = itr2.next();
if(key.equals("3")) myMap.put(key+"new", "new3");
}
System.out.println("HashMap nach Iterator: "+myMap);
}
}
Die Ausgabe wird sein:
ConcurrentHashMap vor Iterator: {1=1, 5=1, 6=1, 3=1, 4=1, 2=1}
ConcurrentHashMap nach Iterator: {1=1, 3new=new3, 5=1, 6=1, 3=1, 4=1, 2=1}
HashMap vor Iterator: {3=1, 2=1, 1=1, 6=1, 5=1, 4=1}
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
at java.util.HashMap$KeyIterator.next(HashMap.java:828)
at com.test.ConcurrentHashMapExample.main(ConcurrentHashMapExample.java:44)
Wie Sie sehen können, wird für das HashMap
eine ConcurrentModificationException
geworfen, weil Sie versuchen, eine Map zu ändern, während Sie sie gerade durchlaufen! (speziell wird die Exception auf der Anweisung geworfen: String key = itr1.next();
)