Quelle est l'utilisation de ConcurrentHashMap
en Java? Quels sont ses avantages? Comment ça marche? Un exemple de code serait utile aussi.
Le but est de fournir une implémentation de HashMap
qui soit threadsafe. Plusieurs threads peuvent lire et écrire dessus sans risque de recevoir des données obsolètes ou corrompues. ConcurrentHashMap
fournit sa propre synchronisation, vous n'avez donc pas à synchroniser les accès à celle-ci de manière explicite.
Une autre caractéristique de ConcurrentHashMap
est qu’elle fournit la méthode putIfAbsent
, qui ajoutera atomiquement un mappage si la clé spécifiée n’existe pas. Considérons le code suivant:
ConcurrentHashMap<String, Integer> myMap = new ConcurrentHashMap<String, Integer>();
// some stuff
if (!myMap.contains("key")) {
myMap.put("key", 3);
}
Ce code n'est pas threadsafe, car un autre thread pourrait ajouter un mappage pour "key"
entre l'appel à contains
et l'appel à put
. La mise en œuvre correcte serait:
myMap.putIfAbsent("key", 3);
ConcurrentHashMap
permet un accès simultané à la carte. HashTables offre également un accès synchronisé à la carte, mais votre carte entière est verrouillée pour effectuer toute opération.
La logique de ConcurrentHashMap est celle de your entire table is not getting locked
, mais uniquement la partie [segments
]. Chaque segment gère sa propre table de hachage. Le verrouillage est appliqué uniquement pour les mises à jour. En cas de récupération, il permet une simultanéité totale.
Prenons quatre threads travaillant simultanément sur une mappe dont la capacité est de 32, la table est partitionnée en quatre segments, chaque segment gérant une table de hachage de capacité. La collection conserve une liste de 16 segments par défaut, chacun étant utilisé pour protéger (ou verrouiller) un seul compartiment de la carte.
Cela signifie que 16 threads peuvent modifier la collection en même temps. Ce niveau de simultanéité peut être augmenté à l'aide de l'argument facultatif concurrencyLevel .
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel)
Comme l’a indiqué l’autre réponse, ConcurrentHashMap propose la nouvelle méthode putIfAbsent()
, similaire à put, sauf que la valeur ne sera pas remplacée si la clé existe.
private static Map<String,String> aMap =new ConcurrentHashMap<String,String>();
if(!aMap.contains("key"))
aMap.put("key","value");
La nouvelle méthode est également plus rapide car elle évite double traversing
comme ci-dessus. La méthode contains
doit localiser le segment et parcourir la table pour trouver la clé, puis la méthode put
doit traverser le compartiment et placer la clé.
La grande différence fonctionnelle est qu’il ne jette pas une exception et/ou ne finit pas par être corrompu lorsque quelqu'un d'autre la modifie pendant que vous l'utilisez.
Avec les collections régulières, si un autre thread ajoute ou supprime un élément pendant que vous y accédez (via l'itérateur), une exception est générée. ConcurrentHashMap leur permet de faire le changement et n'arrête pas votre thread.
Notez que cela ne fait aucune sorte de synchronisation ou de promesse de synchronisation concernant la visibilité à un point dans le temps du changement d'un thread à l'autre. (Cela ressemble un peu à une isolation de base de données lue, plutôt qu’à une mappe synchronisée qui se comporte davantage comme une isolation de base de données sérialisable. (Ancienne école verrouillable SQL sérialisable, et non multiversion Oracle sérialisable :))
L’utilisation la plus courante que je connaisse consiste à mettre en cache des informations dérivées immuables dans des environnements App Server où plusieurs threads peuvent accéder à la même chose, et peu importe si deux calculent la même valeur de cache et la mettent deux fois, car ils s’entrelacent. , etc. (par exemple, il est largement utilisé dans la structure Spring WebMVC pour conserver une configuration dérivée du temps d’exécution, telle que des mappages d’URL vers des méthodes de gestionnaire.)
Il peut être utilisé pour la mémoisation:
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));
};
Bonjour les gars aujourd'hui, nous avons discuté de la ConcurrentHashMap.
Qu'est-ce que ConcurrentHashMap?
ConcurrentHashMap est une classe introduite dans Java 1.5 qui implémente ConcurrentMap ainsi que l'interface Serializable. ConcurrentHashMap améliore le HashMap lorsqu'il traite plusieurs Theading. Comme nous le savons lorsque l’application a plusieurs threads, HashMap n’est pas un bon choix en raison de problèmes de performances.
Il y a le point clé de ConcurrentHashMap.
Voici la construction ConcurrentHashMap.
ConcurrentHashMap m = new ConcurrentHashMap () ;: Crée une nouvelle carte vide avec une capacité initiale par défaut (16), un facteur de charge (0.75) et un paramètre concurrencyLevel (16).
ConcurrentHashMap m = new ConcurrentHashMap (int initialCapacity) ;: crée une nouvelle carte vide avec la capacité initiale spécifiée, avec un facteur de charge par défaut (0.75) et concurrencyLevel (16).
ConcurrentHashMap m = new ConcurrentHashMap (int initialCapacity, float loadFactor) ;: crée une nouvelle carte vide avec la capacité initiale et le facteur de charge spécifiés, ainsi que le paramètre concurrencyLevel (16) par défaut.
ConcurrentHashMap m = new ConcurrentHashMap (int initialCapacity, float loadFactor, int concurrencyLevel) ;: crée une nouvelle carte vide avec la capacité initiale, le facteur de charge et le niveau de simultanéité spécifiés.
ConcurrentHashMap m = new ConcurrentHashMap (Map m) ;: Crée une nouvelle carte avec les mêmes mappages que la carte donnée.
ConcurretHashMap a une méthode nommée est putIfAbsent (); Cette méthode empêche de stocker la clé en double, veuillez vous reporter à l'exemple ci-dessous.
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);
}
}
1.ConcurrentHashMap est thread-safe, c'est-à-dire que le code est accessible par un seul thread à la fois.
2.ConcurrentHashMap synchronise ou verrouille certaines parties de la carte. Pour optimiser les performances de ConcurrentHashMap, Map est divisé en différentes partitions en fonction du niveau de simultanéité. Ainsi, nous n'avons pas besoin de synchroniser tout l'objet Map.
3. Le niveau de simultanéité par défaut est 16; par conséquent, la carte est divisée en 16 parties et chaque partie est régie par un verrou différent permettant à 16 unités d'exécution de fonctionner.
4.ConcurrentHashMap n'autorise pas les valeurs NULL. La clé ne peut donc pas être null dans ConcurrentHashMap.