ConcurrentHashMap in Java?

Lesezeit: 7 Minuten

Benutzer-Avatar
Praveen

Wozu benutzt man ConcurrentHashMap auf Java? Was sind seine Vorteile? Wie funktioniert es? Beispielcode wäre auch hilfreich.

Benutzer-Avatar
danben

Es geht darum, eine Implementierung von bereitzustellen HashMap das ist threadsicher. Mehrere Threads können darauf lesen und darauf schreiben, ohne dass die Möglichkeit besteht, veraltete oder beschädigte Daten zu erhalten. ConcurrentHashMap bietet eine eigene Synchronisierung, sodass Sie Zugriffe darauf nicht explizit synchronisieren müssen.

Ein weiteres Merkmal von ConcurrentHashMap ist, dass es die putIfAbsent Methode, die wird atomar Fügen Sie eine Zuordnung hinzu, wenn der angegebene Schlüssel nicht vorhanden ist. Betrachten Sie den folgenden Code:

ConcurrentHashMap<String, Integer> myMap = new ConcurrentHashMap<String, Integer>();

// some stuff

if (!myMap.contains("key")) {
  myMap.put("key", 3);
}

Dieser Code ist nicht threadsicher, da ein anderer Thread eine Zuordnung für hinzufügen könnte "key" zwischen dem Anruf an contains und der Aufruf an put. Die korrekte Implementierung wäre:

myMap.putIfAbsent("key", 3);

  • Ich würde es eher als “sicher unsynchronisiert” beschreiben. Es ermöglicht, dass zwei Threads gleichzeitig im Inneren herumspielen und verspricht, danach in einem konsistenten Zustand zu enden.

    – Affe

    14. Mai 2010 um 17:42 Uhr

  • Die Synchronisierung ist keine (externe) Ordnungsgarantie.

    – Danben

    14. Mai 2010 um 17:47 Uhr


  • Es ist keine Garantie dafür, dass Threads, die den Monitor anfordern, ihn in der angeforderten Reihenfolge erhalten, aber es ist eine Happening-Before-Garantie, dass, sobald ein Thread den Monitor erfasst und mit der Änderung der Zuordnung beginnt, niemand sonst ihn sehen wird, bis die Änderung abgeschlossen ist . In der Concurrent Map könnte ein Thread einen Put starten und dann für eine lange Zeit nicht erneut geplant werden, und andere Threads können Abrufe ausführen, die den laufenden Put nicht sehen.

    – Affe

    14. Mai 2010 um 17:57 Uhr

  • Da die Gets die in Bearbeitung befindlichen Puts nicht sehen, führt dies nicht zu einem inkonsistenten Zustand?

    – Vanchinathan Chandrasekaran

    27. April 2012 um 16:03 Uhr

  • Mir ist aufgefallen, dass Sie a verwendet haben String Schlüssel; wenn string1.equals(string2)&&string1!=string2 Bekomme ich den Artikel trotzdem in die ConcurrentHashMap?

    – Andreas Wyld

    19. November 2012 um 13:38 Uhr

ConcurrentHashMap Gleichzeitigen Zugriff auf die Karte zulassen. Auch HashTables bietet synchronisierten Zugriff auf die Karte, aber Ihre gesamte Karte ist gesperrt, um Operationen auszuführen.

Die Logik hinter ConcurrentHashMap ist die your entire table is not getting lockedaber nur der Teil[segments]. Jedes Segment verwaltet seine eigene HashTable. Die Sperrung wird nur für Updates angewendet. Im Falle von Abrufen ermöglicht es vollständige Parallelität.

Nehmen wir an, vier Threads arbeiten gleichzeitig an einer Map, deren Kapazität 32 beträgt, die Tabelle ist in vier Segmente unterteilt, wobei jedes Segment eine Hash-Tabelle der Kapazität verwaltet. Die Sammlung verwaltet standardmäßig eine Liste mit 16 Segmenten, von denen jedes verwendet wird, um einen einzelnen Bucket der Karte zu schützen (oder zu sperren).

Geben Sie hier die Bildbeschreibung ein

Dies bedeutet effektiv, dass 16 Threads die Sammlung gleichzeitig ändern können. Dieser Grad an Parallelität kann mit dem optionalen erhöht werden concurrencyLevel-Konstruktor Streit.

public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel)

Wie in der anderen Antwort angegeben, bietet die ConcurrentHashMap eine neue Methode putIfAbsent() ähnlich wie put, außer dass der Wert nicht überschrieben wird, wenn der Schlüssel vorhanden ist.

private static Map<String,String> aMap =new ConcurrentHashMap<String,String>();

if(!aMap.contains("key"))
   aMap.put("key","value");

Das neue Verfahren ist auch schneller, da es vermeidet double traversing wie oben. contains Die Methode muss das Segment lokalisieren und die Tabelle durchlaufen, um den Schlüssel und erneut die Methode zu finden put muss den Eimer durchqueren und den Schlüssel stecken.

  • Standardmäßig ist die Größe 32 , wie kommt es dann, dass 4 Threads Segmente der Größe 16 erstellen können. Wäre es nicht 8

    – jayendra bhatt

    25. Mai 2017 um 8:39 Uhr

Benutzer-Avatar
Affe

Der wirklich große funktionale Unterschied besteht darin, dass es keine Ausnahme auslöst und/oder beschädigt wird, wenn jemand anderes es ändert, während Sie es verwenden.

Wenn bei regulären Sammlungen ein anderer Thread ein Element hinzufügt oder entfernt, während Sie darauf zugreifen (über den Iterator), wird eine Ausnahme ausgelöst. ConcurrentHashMap lässt sie die Änderung vornehmen und stoppt Ihren Thread nicht.

Wohlgemerkt gibt es keinerlei Synchronisierungsgarantien oder Versprechungen über die zeitpunktbezogene Sichtbarkeit der Änderung von einem Thread zum anderen. (Es ist eine Art Datenbankisolation mit Lesebestätigung, eher als eine synchronisierte Karte, die sich eher wie eine serialisierbare Datenbankisolation verhält. (Serialisierbares SQL mit Zeilensperre der alten Schule, nicht serialisierbare Oracle-artige Multiversion :))

Die häufigste Verwendung, die ich kenne, ist das Zwischenspeichern unveränderlicher abgeleiteter Informationen in App Server-Umgebungen, in denen viele Threads möglicherweise auf dasselbe zugreifen, und es spielt keine Rolle, ob zwei zufällig denselben Cache-Wert berechnen und ihn zweimal eingeben, weil sie sich verzahnen usw. (z. B. wird es im Spring WebMVC-Framework häufig verwendet, um von der Laufzeit abgeleitete Konfigurationen wie Zuordnungen von URLs zu Handler-Methoden zu speichern.)

  • Das stimmt überhaupt nicht. Die Javadocs geben explizit an, dass alle Operationen threadsicher sind.

    – Danben

    14. Mai 2010 um 17:43 Uhr

  • Alle Operationen sind threadsicher, aber es gibt keine Ereignisse vor dem Versprechen, wie es bei einer synchronisierten Karte der Fall wäre. Was Sie sehen, wenn Sie in eine ConcurrentHashMap schauen, sind die Ergebnisse der zuletzt abgeschlossenen Operationen. Einige davon haben möglicherweise deutlich später begonnen als zu dem Zeitpunkt, als Sie mit dem Versuch begonnen haben, nachzusehen. Es funktioniert eher wie eine Read-Committed-Datenbankisolation, während eine synchronisierte Karte eher wie eine serialisierbare Datenbankisolation funktioniert.

    – Affe

    14. Mai 2010 um 17:46 Uhr


Es kann zum Merken verwendet werden:

import java.util.concurrent.ConcurrentHashMap;
public static Function<Integer, Integer> fib = (n) -> {
  Map<Integer, Integer> cache = new ConcurrentHashMap<>();
  if (n == 0 || n == 1) return n;
  return cache.computeIfAbsent(n, (key) -> HelloWorld.fib.apply(n - 2) + HelloWorld.fib.apply(n - 1));
};

1.ConcurrentHashMap ist Thread-sicher, d. h. auf den Code kann jeweils von einem einzelnen Thread zugegriffen werden.

2.ConcurrentHashMap synchronisiert oder sperrt den bestimmten Teil der Karte. Um die Leistung von ConcurrentHashMap zu optimieren, wird Map je nach Parallelitätsebene in verschiedene Partitionen unterteilt. Damit wir nicht das gesamte Map-Objekt synchronisieren müssen.

3. Die Standard-Parallelitätsebene ist 16, dementsprechend ist die Karte in 16 Teile unterteilt und jeder Teil wird mit einer anderen Sperre geregelt, was bedeutet, dass 16 Threads arbeiten können.

4.ConcurrentHashMap erlaubt keine NULL-Werte. Der Schlüssel darf also in ConcurrentHashMap nicht null sein.

Benutzer-Avatar
JegsVala

Hallo Leute, heute haben wir die ConcurrentHashMap besprochen.
Was ist ConcurrentHashMap?

ConcurrentHashMap ist eine in Java 1.5 eingeführte Klasse, die sowohl die ConcurrentMap als auch die Serializable-Schnittstelle implementiert. ConcurrentHashMap erweitert die HashMap, wenn es um mehrere Theading geht. Wie wir wissen, ist HashMap keine gute Wahl, wenn die Anwendung über mehrere Threads verfügt, da Leistungsprobleme aufgetreten sind.

Es gibt einige Schlüsselpunkte von ConcurrentHashMap.

  • Die zugrunde liegende Datenstruktur für ConcurrentHashMap ist HashTable.
  • ConcurrentHashMap ist eine Klasse. Diese Klasse ist Thread-sicher, was bedeutet, dass mehrere Threads ohne Komplikationen auf ein einzelnes Thread-Objekt zugreifen können.
  • Das ConcurretnHashMap-Objekt wird gemäß der Parallelitätsebene in die Anzahl der Segmente unterteilt.
  • Die Standard-Parallelitätsebene von ConcurrentHashMap ist 16.
  • In ConcurrentHashMap kann eine beliebige Anzahl von Threads den Abrufvorgang ausführen, aber für die Aktualisierung im Objekt muss der Thread das bestimmte Segment sperren, in dem der Thread arbeiten möchte.
  • Diese Art von Verriegelungsmechanismus ist als Segment-Locking ODER Bucket-Locking bekannt.
  • In ConcurrentHashMap werden die 16 Aktualisierungsvorgänge gleichzeitig ausgeführt.
  • Das Einfügen von Nullen ist in ConcurrentHashMap nicht möglich.

Hier ist die ConcurrentHashMap-Konstruktion.

  1. ConcurrentHashMap m=new ConcurrentHashMap();: Erstellt eine neue, leere Map mit einer standardmäßigen anfänglichen Kapazität (16), einem Lastfaktor (0,75) und einem Parallelitätslevel (16).

  2. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity);: Erstellt eine neue, leere Map mit der angegebenen Anfangskapazität und mit dem standardmäßigen Lastfaktor (0,75) und concurrencyLevel (16).

  3. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor);: Erstellt eine neue, leere Map mit der angegebenen anfänglichen Kapazität und dem angegebenen Lastfaktor und mit dem standardmäßigen concurrencyLevel (16).

  4. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel);: Erstellt eine neue, leere Map mit der angegebenen Anfangskapazität, dem Lastfaktor und dem Parallelitätslevel.

  5. ConcurrentHashMap m=new ConcurrentHashMap(Map m);: Erstellt eine neue Map mit denselben Zuordnungen wie die gegebene Map.

ConcurretHashMap hat eine Methode namens is putIfAbsent(); Diese Methode verhindert, dass der doppelte Schlüssel gespeichert wird. Siehe das folgende Beispiel.

    import java.util.concurrent.*; 

     class ConcurrentHashMapDemo { 
     public static void main(String[] args) 
     { 
         ConcurrentHashMap m = new ConcurrentHashMap(); 
          m.put(1, "Hello"); 
          m.put(2, "Vala"); 
          m.put(3, "Sarakar"); 

         // Here we cant add Hello because 1 key 
         // is already present in ConcurrentHashMap object 

            m.putIfAbsent(1, "Hello"); 

         // We can remove entry because 2 key 
         // is associated with For value 

            m.remove(2, "Vala"); 

        // Now we can add Vala

            m.putIfAbsent(4, "Vala"); 


            System.out.println(m); 
      } 
}  

1088150cookie-checkConcurrentHashMap in Java?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy