Java 中的 ConcurrentHashMap

Java 中的 ConcurrentHashMap

先决条件: ConcurrentMap

ConcurrentHashMap 类被引入到 JDK 1.5 中,属于 java.util.concurrent 包,它实现了 ConcurrentMap 接口和 Serializable 接口。ConcurrentHashMap 是一个 HashMap 的增强版,我们知道,在应用程序中处理线程时,HashMap 在性能方面并不是一个很好的选择,因为 HashMap 的表现不佳。

ConcurrentHashMap 是 Java 中 Map 接口的线程安全实现,这意味着多个线程可以同时访问它而不会出现任何同步问题。它是 java.util.concurrent 包的一部分,并在 Java 5 中作为传统的 HashMap 类的可扩展替代品被引入。

ConcurrentHashMap 的一个关键特征是它提供了细粒度锁定,这意味着它仅锁定正在修改的部分而不是整个映射。这使得它在并发操作方面具有高度的可扩展性和效率。此外,ConcurrentHashMap 还提供了各种方法,用于原子操作,如 putIfAbsent(),replace() 和 remove()。

这是一个使用 ConcurrentHashMap 的简单示例:

import java.util.concurrent.ConcurrentHashMap;
 
public class Main {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
 
        //向映射中添加元素
        map.put("A", 1);
        map.put("B", 2);
        map.put("C", 3);
 
        System.out.println("映射的大小:" + map.size());
 
        //从映射中获取值
        int valueA = map.get("A");
        System.out.println("A 的值:" + valueA);
 
        //从映射中移除元素
        map.remove("B");
        System.out.println("映射的大小:" + map.size());
    }
}

输出结果:

映射的大小:3
A 的值:1
映射的大小:2

ConcurrentHashMap 的关键点:

  • ConcurrentHashMap 的底层数据结构是 Hashtable。
  • ConcurrentHashMap 类是线程安全的,即多个线程可以在单个对象上操作而没有任何复杂性。
  • 同时可以有任意数量的线程适用于读操作,而不锁定 ConcurrentHashMap 对象,在 HashMap 中不存在这种情况。
  • 在 ConcurrentHashMap 中,对象根据并发级别分成多个段。
  • ConcurrentHashMap 的默认并发级别为 16。
  • 在 ConcurrentHashMap 中,可以同时对任意数量的线程执行检索操作,但是要更新对象,则线程必须锁定要操作的特定段。这种锁定机制称为 段锁定或桶锁定 。因此,线程可以执行 16 个更新操作。
  • 在 ConcurrentHashMap 中,不能插入空对象作为键或值。

声明:

public class ConcurrentHashMap<K,​V> extends AbstractMap<K,​V> implements ConcurrentMap<K,​V>, Serializable

这里, K 是键 Object 类型, V 是值 Object 类型。

ConcurrentHashMap 的层次结构:

Java 中的 ConcurrentHashMap

它实现了 **Serializable、ConcurrentMap <K,​ V> 、Map<K,​ V> ** 接口,并扩展了 **AbstractMap <K, ​V> ** 类。

ConcurrentHashMap 的构造函数:

  • 并发级别(Concurrency-Level): 是指同时更新映射表的线程数。实现会进行内部大小调整,以尽力容纳这些线程。
  • 负载因子(Load-Factor): 用于控制重分配的阈值。
  • 初始容量(Initial Capacity): 实现最初提供给元素的一定数量设施。若此映射表的容量为10,即可存储10个条目。

1. ConcurrentHashMap() : 创建具有默认初始容量(16)、默认负载因子(0.75)和默认并发级别(16)的新空映射表。

ConcurrentHashMap<K, V> chm = new ConcurrentHashMap<>();

2. ConcurrentHashMap(int initialCapacity) : 创建具有指定初始容量和默认负载因子(0.75)和默认并发级别(16)的新空映射表。

ConcurrentHashMap<K, V> chm = new ConcurrentHashMap<>(int initialCapacity);

3. ConcurrentHashMap(int initialCapacity, float loadFactor) : 创建具有指定初始容量和负载因子以及默认并发级别(16)的新空映射表。

ConcurrentHashMap<K, V> chm = new ConcurrentHashMap<>(int initialCapacity, float loadFactor);

4. ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) : 创建具有指定初始容量、负载因子和并发级别的新空映射表。

ConcurrentHashMap<K, V> chm = new ConcurrentHashMap<>(int initialCapacity, float loadFactor, int concurrencyLevel);

5. ConcurrentHashMap(Map m) : 创建一个具有给定映射的相同映射表。

ConcurrentHashMap<K, V> chm = new ConcurrentHashMap<>(Map m);

示例:

// Java program to demonstrate working of ConcurrentHashMap
 
import java.util.concurrent.*;
 
class ConcurrentHashMapDemo {
 
    public static void main(String[] args)
    {
        // create an instance of
        // ConcurrentHashMap
        ConcurrentHashMap<Integer, String> m
            = new ConcurrentHashMap<>();
 
        // Insert mappings using
        // put method
        m.put(100, "Hello");
        m.put(101, "Geeks");
        m.put(102, "Geeks");
 
        // Here we cant add Hello because 101 key
        // is already present in ConcurrentHashMap object
        m.putIfAbsent(101, "Hello");
 
        // We can remove entry because 101 key
        // is associated with For value
        m.remove(101, "Geeks");
 
        // Now we can add Hello
        m.putIfAbsent(103, "Hello");
 
        // We cant replace Hello with For
        m.replace(101, "Hello", "For");
        System.out.println(m);
    }
}

输出(Output)

{100=Hello, 102=Geeks, 103=Hello}

ConcurrentHashMap的基本操作

1. 添加元素

要向ConcurrentHashMap添加映射,可以使用put()或putAll()方法。下面的示例代码解释了这两种方法。 2. 查找元素

要在ConcurrentHashMap中查找元素,可以使用get()方法。如果该键不存在,则返回null值,如果存在,则返回映射值。

3. 删除元素

要删除ConcurrentHashMap中的元素,可以使用remove()方法。如果存在映射,则返回映射值。如果不存在映射,则返回null值。

4. 更新元素

要更新ConcurrentHashMap中的元素,可以使用replace()方法。如果键存在,则用新的值替换旧的值,并返回旧的值。如果键不存在,则返回null值。

5. 遍历元素

可以使用迭代器来遍历ConcurrentHashMap中的元素。迭代器可以通过使用keySet()、values()或entrySet()方法获得。

// Java程序,演示添加元素到ConcurrentHashMap
 
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
 
public class AddingElementsToConcuurentHashMap {
 
    public static void main(String[] args)
    {
        // 创建ConcurrentHashMap
        ConcurrentHashMap<String, String> my_cmmap
            = new ConcurrentHashMap<String, String>();
 
        // 使用put()方法将元素添加到映射中
        my_cmmap.put("1", "1");
        my_cmmap.put("2", "1");
        my_cmmap.put("3", "1");
        my_cmmap.put("4", "1");
        my_cmmap.put("5", "1");
        my_cmmap.put("6", "1");
 
        // 打印映射
        System.out.println("Mappings of my_cmmap : "
                           + my_cmmap);
 
        // 创建另一个ConcurrentHashMap
        ConcurrentHashMap<String, String> new_chm
            = new ConcurrentHashMap<>();
 
        // 将my_cmmap中的映射复制到新映射中
        new_chm.putAll(my_cmmap);
 
        // 显示新映射
        System.out.println("New mappings are: " + new_chm);
    }
}

输出结果

Mappings of my_cmmap : {1=1, 2=1, 3=1, 4=1, 5=1, 6=1}
New mappings are: {1=1, 2=1, 3=1, 4=1, 5=1, 6=1}

2. 删除元素

要删除映射,我们可以使用ConcurrentHashmap类的remove(Object key)方法。如果key不存在于映射中,则此函数不执行任何操作。要清除整个映射,我们可以使用clear()方法。

// Java程序,演示从ConcurrentHashMap中删除元素
 
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
 
public class RemoveElementsFromConcurrentHashMap {
 
    public static void main(String[] args)
    {
        // 创建ConcurrentHashMap
        Map<String, String> my_cmmap
            = new ConcurrentHashMap<String, String>();
 
        // 使用put()方法将元素添加到映射中
        my_cmmap.put("1", "1");
        my_cmmap.put("2", "1");
        my_cmmap.put("3", "1");
        my_cmmap.put("4", "1");
        my_cmmap.put("5", "1");
        my_cmmap.put("6", "1");
 
        // 打印映射
        System.out.println("Map: " + my_cmmap);
        System.out.println();
 
        // 使用remove()方法删除具有现有键6的映射
        String valueRemoved = my_cmmap.remove("6");
 
        // 删除后打印映射
        System.out.println(
            "After removing mapping with key 6:");
        System.out.println("Map: " + my_cmmap);
        System.out.println("Value removed: "
                           + valueRemoved);
        System.out.println();
 
        // 使用remove()方法删除具有不存在键10的映射
        valueRemoved = my_cmmap.remove("10");
 
        // 删除后打印映射
        System.out.println(
            "After removing mapping with key 10:");
        System.out.println("Map: " + my_cmmap);
        System.out.println("Value removed: "
                           + valueRemoved);
        System.out.println();
 
        // 现在使用clear()方法清除映射
        my_cmmap.clear();
 
        // 打印清理后的映Map
        System.out.println("Map after use of clear(): "
                           + my_cmmap);
    }
}

输出结果

Map: {1=1, 2=1, 3=1, 4=1, 5=1, 6=1}

After removing mapping with key 6:
Map: {1=1, 2=1, 3=1, 4=1, 5=1}
Value removed: 1

After removing mapping with key 10:
Map: {1=1, 2=1, 3=1, 4=1, 5=1}
Value removed: null

Map after use of clear(): {}

3. 访问元素

我们可以使用get()方法访问ConcurrentHashMap的元素,下面给出了一个例子。

// Java程序演示访问ConcurrentHashMap的元素
import java.util.concurrent.*;

class AccessingElementsOfConcurrentHashMap {

    public static void main(String[] args)
    {

        // 创建ConcurrentHashMap实例
        ConcurrentHashMap chm
            = new ConcurrentHashMap();

        // 使用put方法插入映射
        chm.put(100, "Geeks");
        chm.put(101, "for");
        chm.put(102, "Geeks");
        chm.put(103, "Contribute");

        // 显示HashMap
        System.out.println("Mappings are: ");
        System.out.println(chm);

        // 显示100的值
        System.out.println("Value associated to "
                                   + "100 is : " + chm.get(100));

        // 获取103的值
        System.out.println("Value associated to "
                                   + "103 is : " + chm.get(103));
    }
}

输出

The Mappings are: 
{100=Geeks, 101=for, 102=Geeks, 103=Contribute}
The Value associated to 100 is : Geeks
The Value associated to 103 is : Contribute

4. 遍历

我们可以使用Iterator接口遍历Collection Framework的任何结构。由于迭代器使用一种类型的数据,我们使用Entry<?, ?>将两种分离的类型解决成兼容格式。然后使用next()方法打印ConcurrentHashMap的元素。

// Java程序遍历ConcurrentHashMap
import java.util.*;
import java.util.concurrent.*;

public class TraversingConcurrentHashMap {

    public static void main(String[] args)
    {

        // 创建ConcurrentHashMap实例
        ConcurrentHashMap chmap
            = new ConcurrentHashMap();

        // 使用put()添加元素
        chmap.put(8, "Third");
        chmap.put(6, "Second");
        chmap.put(3, "First");
        chmap.put(11, "Fourth");

        // 创建ConcurrentHashMap的迭代器
        Iterator>
            itr = chmap.entrySet().iterator();

        // 使用hasNext()方法检查是否有下一个元素
        // 使用next()方法检索下一个元素
        while (itr.hasNext()) {
            ConcurrentHashMap.Entry entry
                = itr.next();
            System.out.println("Key = " + entry.getKey()
                                       + ", Value = "
                                       + entry.getValue());
        }
    }
}

输出

Key = 3, Value = First
Key = 6, Value = Second
Key = 8, Value = Third
Key = 11, Value = Fourth

方法 of ConcurrentHashMap

  • K - map中键的类型。
  • V - 映射在map中的值的类型。

METHOD | DESCRIPTION
—|—
clear() | 从 map 中移除所有的映射。
compute​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction) | 尝试计算指定键的映射及其当前映射值(如果当前没有映射值则为 null)。
computeIfAbsent​(K key, Function<? super K,​? extends V> mappingFunction) | 如果指定的键尚未与值关联,则尝试使用给定的映射函数计算其值并将其输入到此映射中(除非为 null)。
computeIfPresent​(K key, BiFunction<? super K,​? super V,​? extends V> remappingFunction) | 如果存在指定键的值,则尝试根据键和其当前映射的值计算新的映射。
contains​(Object value) | 在此表中测试是否有一些键映射到指定的值。
containsKey​(Object key) | 测试指定的对象是否为此表中的键。
containsValue​(Object value) | 如果此 map 将一个或多个键映射到指定的值,则返回 true。
elements() | 返回此表中值的枚举。
entrySet() | 返回此 map 中包含的映射的 Set 视图。
equals​(Object o) | 将指定对象与此 map 进行比较以测试相等性。
forEach​(long parallelismThreshold, BiConsumer<? super K,​? super V> action) | 对于每一个(key,value)执行给定的操作。
forEach​(long parallelismThreshold, BiFunction<? super K,​? super V,​? extends U> transformer, Consumer<? super U> action) | 对于每一个非 null 变换(key,value),执行给定的操作。
forEachEntry​(long parallelismThreshold, Consumer<? super Map.Entry<K,​V>> action) | 对于每一个 entry,执行给定的操作。
forEachEntry​(long parallelismThreshold, Function<Map.Entry<K,​V>,​? extends U> transformer, Consumer<? super U> action) | 对于每一个非 null 变换的 entry,执行给定的操作。
forEachKey​(long parallelismThreshold, Consumer<? super K> action) | 对每个键执行给定的操作。
forEachKey​(long parallelismThreshold, Function<? super K,​? extends U> transformer, Consumer<? super U> action) | 对于每一个非 null 变换后的 key,执行给定的操作。
forEachValue​(long parallelismThreshold, Consumer<? super V> action) | 对每个 value执行给定的操作。
forEachValue​(long parallelismThreshold, Function<? super V,​? extends U> transformer, Consumer<? super U> action) | 对于每一个非 null 变换后的 value,执行给定的操作。
get​(Object key) | 返回指定键所映射的值,如果此 map 中未映射该键,则返回 null。
getOrDefault​(Object key, V defaultValue) | 返回指定键所映射的值,如果此 map 中未映射该键,则返回指定的默认值。
hashCode() | 返回此 map 的哈希码。
isEmpty() | 如果此 map 不包含任何映射,则返回 true。
keySet() | 返回此 map 中包含的键的 Set 视图。
merge​(K key, V value, BiFunction<? super V,​? super V,​? extends V> remappingFunction) | 如果指定的键还没有与值相关联或已经与 null 关联,则将指定的键与给定的非 null 值关联。
put​(K key, V value) | 将指定的值与此 map 中的指定键相关联。
putAll​(Map<? extends K,​? extends V> m) | 将指定 map 中的所有映射复制到此 map 中。
putIfAbsent​(K key, V value) | 如果指定的键尚未与值关联(或映射为 null),则将其与指定的值相关联并返回 null,否则返回当前值。
reduce​(long parallelismThreshold, BiFunction<? super K,​? super V,​V> transformer, BiFunction<V,​V,​? extends V> reducer) | 对于每一对(key, value)执行给定的变换,并在所有非 null 转换的值上执行给定的 reduce 操作。
reduceEntries​(long parallelismThreshold, Function<Map.Entry<K,​V>,​? extends R> transformer, BiFunction<R,​R,​? extends R> reducer) | 对于每一个 entry 执行给定的变换,并在所有非 null 转换的结果上执行给定的 reduce 操作。
reduceKeys​(long parallelismThreshold, Function<? super K,​? extends U> transformer, BiFunction<U,​U,​? extends U> reducer) | 对于每个键执行给定的变换,并在所有非 null 转换的值上执行给定的 reduce 操作。
reduceValues​(long parallelismThreshold, Function<? super V,​? extends U> transformer, BiFunction<U,​U,​? extends U> reducer) | 对于每个 value 执行给定的变换,并在所有非 null 转换的值上执行给定的 reduce 操作。
remove​(Object key) | 如果存在键的映射关系,则将其从此 map 中移除。
remove​(Object key, Object value) | 仅当指定键的当前映射为指定值时,才从此 map 中移除该键的映射关系。
replace​(K key, V value) | 只有在当前映射到指定值时,才替换指定键的当前映射。
replace​(K key, V oldValue, V newValue) | 仅当当前映射到指定值时,才替换指定键的当前映射。
replaceAll​(BiFunction<? super K,​? super V,​? extends V> function) | 将此 map 中的每个映射替换为通过给定映射函数计算的新值。
size() | 返回此 map 中的键-值映射关系数。
toString() | 返回此 map 的字符串表示形式。
values() | 返回此 map 中包含的值的 Collection 视图。
keys() | 返回此表中键的枚举。
keySet() | 返回包含此映射中所包含的键的Set视图。
keySet​(V mappedValue) | 使用给定的常映射值返回此映射中的键的Set视图(即,对于任何添加,使用Collection.add(E)和Collection.addAll(Collection))。
mappingCount() | 返回映射数。
merge​(K key, V value, BiFunction<? super V,​? super V,​? extends V> remappingFunction) | 如果指定的键没有与非空值关联,则将其与给定值相关联。
newKeySet() | 从给定类型到Boolean.TRUE创建一个ConcurrentHashMap支持的新Set。
newKeySet​(int initialCapacity) | 从给定类型到Boolean.TRUE创建一个支持的新ConcurrentHashMap Set。
put​(K key, V value) | 在此表中将指定键映射到指定值。
putAll​(Map<? extends K,​? extends V> m) | 将指定映射中的所有映射复制到此映射中。
putIfAbsent​(K key, V value) | 如果指定的键还没有与值相关联,则将其与给定的值相关联。
reduce​(long parallelismThreshold, BiFunction<? super K,​? super V,​? extends U> transformer, BiFunction<? super U,​? super U,​? extends U> reducer) | 使用给定的规约器组合所有(键,值)对的给定转换的结果的累积结果,如果没有,则返回null。
reduceEntries​(long parallelismThreshold, BiFunction<Map.Entry<K,​V>,​Map.Entry<K,​V>,​? extends Map.Entry<K,​V>> reducer) | 使用给定的规约器组合所有条目的结果的累积结果,如果没有,则返回null。
reduceEntries​(long parallelismThreshold, Function<Map.Entry<K,​V>,​? extends U> transformer, BiFunction<? super U,​? super U,​? extends U> reducer) | 使用给定的规约器组合所有条目的给定转换的结果的累积结果,如果没有,则返回null。
reduceEntriesToDouble​(long parallelismThreshold, ToDoubleFunction<Map.Entry<K,​V>> transformer, double basis, DoubleBinaryOperator reducer) | 使用给定的规约器组合所有条目的给定转换的结果的累积结果,以及给定的基础值作为标识值。
reduceEntriesToInt​(long parallelismThreshold, ToIntFunction<Map.Entry<K,​V>> transformer, int basis, IntBinaryOperator reducer) | 使用给定的规约器组合所有条目的给定转换的结果的累积结果,以及给定的基础值作为标识值。
reduceEntriesToLong​(long parallelismThreshold, ToLongFunction<Map.Entry<K,​V>> transformer, long basis, LongBinaryOperator reducer) | 使用给定的规约器组合所有条目的给定转换的结果的累积结果,以及给定的基础值作为标识值。
reduceKeys​(long parallelismThreshold, BiFunction<? super K,​? super K,​? extends K> reducer) | 使用给定的规约器组合所有键的结果的累积结果。
reduceValuesToLong​(long parallelismThreshold, ToLongFunction<? super V> transformer, long basis, LongBinaryOperator reducer) 返回通过使用给定的reducer组合值来累积所有值的结果,给定的基值作为标识值,或者如果没有则返回null。

方法 描述
reduceValuesToLong​(long parallelismThreshold, ToLongFunction<? super V> transformer, long basis, LongBinaryOperator reducer) 使用给定的归约器(reducer)和给定的基值(basis)对所有值进行给定的转换(transformation)的累计,并返回结果。
remove​(Object key) 从此映射中删除键和其对应的值。
remove​(Object key, Object value) 仅在当前映射到给定值时,删除该键的条目。
replace​(K key, V value) 仅当当前映射到某个值时,替换键的条目。
replace​(K key, V oldValue, V newValue) 仅在当前映射到给定值时,替换该键的条目。
search​(long parallelismThreshold, BiFunction<? super K,​? super V,​? extends U> searchFunction) 在每个键值对上应用给定的搜索函数,并返回非空结果,否则返回null。
searchEntries​(long parallelismThreshold, Function<Map.Entry<K,​V>,​? extends U> searchFunction) 在每个条目上应用给定的搜索函数,并返回非空结果,否则返回null。
searchKeys​(long parallelismThreshold, Function<? super K,​? extends U> searchFunction) 在每个键上应用给定的搜索函数,并返回非空结果,否则返回null。
searchValues​(long parallelismThreshold, Function<? super V,​? extends U> searchFunction) 在每个值上应用给定的搜索函数,并返回非空结果,否则返回null。
toString() 返回此映射的字符串表示形式。
values() 返回此映射中所包含的值的Collection视图。

在java.util.AbstractMap类中声明的方法

方法 描述
clone() 返回此AbstractMap实例的浅拷贝:键和值本身没有被克隆。
isEmpty() 如果此映射不包含键值映射,则返回true。
size() 返回此映射中的键值映射数。

在java.util.concurrent.ConcurrentMap接口中声明的方法

方法 描述
forEach​(BiConsumer<? super K,​? super V> action) 对此映射中的每个条目执行给定的操作,直到处理完所有条目或操作引发异常。
replaceAll​(BiFunction<? super K,​? super V,​? extends V> function) 用调用该条目上给定函数的结果替换每个条目的值,直到处理完所有条目或函数引发异常。

ConcurrentHashMap vs Hashtable

HashTable

  • Hashtable 是Map数据结构的一种实现
  • 这是一个受遗留的类,在Hashtable实例上,它的所有方法都使用synchronized关键字进行同步。
  • 线程安全,因为其方法是同步的

ConcurrentHashMap

  • ConcurrentHashMap 实现Map数据结构,也像Hashtable一样提供线程安全。
  • 它通过将完整的哈希表数组分成段或部分,并允许对这些段进行并行访问来工作。
  • 在哈希图桶水平上的锁定控制更精细。
  • 在应用程序中需要非常高的并发性时,请使用ConcurrentHashMap。
  • 它是一种无需同步整个映射即可实现线程安全的数据结构。
  • 读取可以非常快,而写入则使用对段级或桶级别进行锁定。
  • 对象级别上没有锁定。
  • 如果一个线程尝试在另一个线程迭代它时修改它,则ConcurrentHashMap不会引发ConcurrentModificationException。
  • ConcurrentHashMap不允许NULL值,因此在ConcurrentHashMap中键不能为空。
  • 如果一个线程尝试在另一个线程迭代它时修改它,则ConcurrentHashMap不会引发ConcurrentModificationException。
属性 Hashtable(散列表) ConcurrentHashMap(并发哈希表)
创建方式 Map ht = new Hashtable(); Map chm = new ConcurrentHashMap();
是否允许 null 键值
是否允许 null 值 不允许(不允许 null 键和值)
线程安全性 是。通过为不同的桶提供单独的锁以确保线程安全性,从而获得更好的性能。提供并发读取访问,无需任何阻塞,从而进一步提高性能。
性能 由于同步开销较大,性能较慢。 比Hashtable更快。当读取操作比写入操作更多时,ConcurrentHashMap是更好的选择。
迭代器 Hashtable使用枚举器来迭代Hashtable对象的值。Hashtable方法keys和elements返回的枚举不具有快速失败特性。 安全故障迭代器:ConcurrentHashMap提供的迭代器是安全故障迭代器,这意味着它不会抛出ConcurrentModificationException异常。

结论:

如果需要线程安全的高并发实现,则建议使用ConcurrentHashMap,而不是Hashtable。

ConcurrentHashMap的优点:

  1. 线程安全:ConcurrentHashMap被设计为支持多个线程同时访问,使其成为需要处理并发访问数据的应用程序的理想选择。
  2. 细粒度锁:与其他同步机制锁定整个数据结构不同,ConcurrentHashMap使用细粒度锁仅锁定正在修改的映射的部分。这使得它在并发操作中高度可扩展和高效。
  3. 原子操作:ConcurrentHashMap提供了多种原子操作方法,如putIfAbsent()、replace()和remove(),可以用于实现复杂的并发算法。
  4. 高性能:由于其细粒度锁机制,即使在重度并发访问下,ConcurrentHashMap也能实现高性能。

ConcurrentHashMap的缺点:

  1. 内存开销更大:ConcurrentHashMap使用的细粒度锁机制需要比其他同步机制更多的内存开销。
  2. 复杂性:ConcurrentHashMap使用的细粒度锁机制可能会使代码更加复杂,特别是对于不熟悉并发编程的开发人员来说。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程