Java >> Tutoriel Java >  >> Tag >> HashMap

Comment synchroniser HashMap en Java

Java HashMap n'est pas synchronisé par défaut. Si nous ajoutons/supprimons des paires clé-valeur d'un HashMap dans une application concurrente où plusieurs threads ajoutent et suppriment des paires, nous pouvons finir par avoir un état incohérent de la carte. Apprenez à synchroniser le hashmap et ConcurrentHashMap en Java.

1. Synchroniser HashMap – ConcurrentHashMap

Notre premier choix devrait toujours être d'utiliser le ConcurrentHashMap class si nous souhaitons utiliser une Map dans un environnement concurrent. ConcurrentHashMap prend en charge l'accès simultané à ses paires clé-valeur par conception. Nous n'avons pas besoin d'effectuer de modifications de code supplémentaires pour activer la synchronisation sur la carte.

Veuillez noter que itérateur obtenu à partir de ConcurrentHashMap ne lance pas ConcurrentModificationException . Cependant, les itérateurs sont conçus pour être utilisés par un seul thread à la fois. Cela signifie que chaque itérateur que nous obtenons à partir d'un ConcurrentHashMap est conçu pour être utilisé par un seul thread et ne doit pas être transmis.

Si nous le faisons, il n'y a aucune garantie qu'un thread verra les modifications apportées à la carte par l'autre thread (sans obtenir un nouvel itérateur à partir de la carte). L'itérateur est garanti pour refléter l'état de la carte au moment de sa création .

Prenons un exemple de travail avec ConcurrentHashMap .

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

public class HashMapExample 
{
    public static void main(String[] args) throws CloneNotSupportedException 
    {
        ConcurrentHashMap<Integer, String> concurrHashMap = new ConcurrentHashMap<>();
        
        //Put require no synchronization
        concurrHashMap.put(1, "A");
        concurrHashMap.put(2, "B");
        
        //Get require no synchronization
        concurrHashMap.get(1);
        
        Iterator<Integer> itr = concurrHashMap.keySet().iterator();
        
        //Using synchronized block is advisable
        synchronized (concurrHashMap) 
        {
            while(itr.hasNext()) {
                System.out.println(concurrHashMap.get(itr.next()));
            }
        }
    }
}

Sortie du programme.

A
B

2. Synchroniser HashMap – Collections.synchronizedMap()

HashMap synchronisé fonctionne également de manière très similaire à ConcurrentHashMap, avec quelques différences.

SynchronizedHashMap il n'autorise qu'un seul thread à effectuer des opérations de lecture/écriture à la fois car toutes ses méthodes sont déclarées synchronisées . ConcurrentHashMap permet à plusieurs threads de travailler indépendamment sur différents segments de la carte. Cela permet un degré plus élevé de simultanéité dans ConcurrentHashMap et améliore ainsi les performances de l'application dans son ensemble.

Les itérateurs des deux classes doivent être utilisés dans synchronized bloquer mais l'itérateur de SynchronizedHashMap est fail-fast . Les itérateurs ConcurrentHashMap ne sont pas rapides.

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class HashMapExample 
{
    public static void main(String[] args) throws CloneNotSupportedException 
    {
        Map<Integer, String> syncHashMap = Collections.synchronizedMap(new HashMap<>());
        
        //Put require no synchronization
        syncHashMap.put(1, "A");
        syncHashMap.put(2, "B");
        
        //Get require no synchronization
        syncHashMap.get(1);
        
        Iterator<Integer> itr = syncHashMap.keySet().iterator();
        
        //Using synchronized block is advisable
        synchronized (syncHashMap) 
        {
            while(itr.hasNext()) {
                System.out.println(syncHashMap.get(itr.next()));
            }
        }
    }
}

Sortie du programme.

A
B

3. Différence entre HashMap synchronisé et ConcurrentHashMap

Identifions quelques différences entre les deux versions de cartes afin que nous puissions décider laquelle choisir dans quelle condition.

  1. Plusieurs threads peuvent ajouter/supprimer des paires clé-valeur de ConcurrentHashMap, tandis qu'un seul thread est autorisé à apporter des modifications dans le cas de SynchronizedHashMap. Cela se traduit par un degré plus élevé de simultanéité dans ConcurrentHashMap.
  2. Pas besoin de verrouiller la carte pour lire une valeur dans ConcurrentHashMap. Une opération de récupération renverra la valeur insérée par l'opération d'insertion terminée la plus récente. Un verrou est également requis pour l'opération de lecture dans SynchronizedHashMap.
  3. ConcurrentHashMap ne lance pas un ConcurrentModificationException si un thread essaie de le modifier pendant qu'un autre itère dessus. L'itérateur reflète l'état de la carte au moment de sa création. SynchronizedHashMap renvoie Iterator, qui échoue rapidement en cas de modification simultanée.

Envoyez-moi vos questions relatives à la synchronisation d'un hashmap en Java .

Bon Apprentissage !!

En savoir plus :

Guide de Java HashMap
HashMap Java Docs
ConcurrentHashMap Java Docs


Balise Java