Java —— ConcurrentHashMap锁分段机制

    xiaoxiao2023-11-16  154

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

    支持检索的完全并发性和更新的高预期并发性的哈希表。 这个类服从相同功能规范如Hashtable ,并且包括对应于每个方法的方法版本Hashtable 。 不过,尽管所有操作都是线程安全的,检索操作并不意味着锁定,并没有为防止所有访问的方式锁定整个表的任何支持。 这个类可以在依赖于线程安全性的程序中与Hashtable完全互Hashtable ,但不依赖于其同步细节。

    检索操作(包括get )通常不阻止,因此可能与更新操作重叠(包括put和remove )。 检索反映了最近完成的更新操作的结果。 (更正式地,对于给定密钥的更新操作熊之前发生与任何(非空关系)检索该键报告经更新的值。)对于聚合操作,比如putAll和clear ,并发检索可能反映插入或移除只有一些条目。 类似地,迭代器,分割器和枚举返回在反映迭代器/枚举创建过程中或之后反映哈希表状态的元素。 他们不抛出ConcurrentModificationException 。 然而,迭代器被设计为一次只能由一个线程使用。 请记住,骨料状态方法的结果,包括size , isEmpty和containsValue通常是有用的,只有当一个地图没有发生在其他线程并发更新。 否则,这些方法的结果反映了可能足以用于监视或估计目的的瞬态状态,但不适用于程序控制。

    当存在太多的冲突(即,具有不同的哈希码但是以表的大小为模数落入相同的时隙的密钥)时,该表被动态扩展,并且每个映射保持大致两个bin的预期平均效果(对应于0.75负载因素阈值调整大小)。 由于映射被添加和删除,这个平均值可能会有很大差异,但是总的来说,这为哈希表保留了普遍接受的时间/空间权衡。 然而,调整这个或任何其他类型的散列表可能是相对较慢的操作。 如果可能,最好提供一个尺寸估计作为可选的initialCapacity构造函数参数。 附加的可选的loadFactor构造函数参数提供了另外的手段,通过指定在计算给定数量的元素时要分配的空间量时使用的表密度来定制初始表容量。 此外,为了与此类的先前版本兼容,构造函数可以可选地指定预期的concurrencyLevel作为内部大小调整的附加提示。 请注意,使用完全相同的许多键hashCode()是降低任何哈希表的hashCode()的一种可靠的方法。 为了改善影响,当按键为Comparable时,该类可以使用键之间的比较顺序来帮助打破关系。

    甲Set投影一个的ConcurrentHashMap可以(使用被创建newKeySet()或newKeySet(int) ),或观察(使用keySet(Object)时仅键是感兴趣的,并且被映射的值是(可能瞬时)不使用或全部取相同的映射值。

    ConcurrentHashMap可以通过使用LongAdder值并通过computeIfAbsent进行初始化,将其用作可缩放的频率映射(直方图或多集的形式)。 例如,要向ConcurrentHashMap<String,LongAdder> freqs添加计数,可以使用freqs.computeIfAbsent(k -> new LongAdder()).increment();

    此类及其视图和迭代器实现所有的可选方法Map个Iterator接口。

    像Hashtable但不像HashMap ,这个类不允许 null用作键或值。

    ConcurrentHashMaps支持一组顺序和并行批量操作,与大多数Stream方法不同,它们被设计为安全并且经常明智地应用,即使是由其他线程同时更新的映射; 例如,当计算共享注册表中的值的快照摘要时。 有三种操作,每种具有四种形式,接受键,值,条目和(键,值)参数和/或返回值的函数。 由于ConcurrentHashMap的元素不以任何特定的方式排序,并且可能会在不同的并行执行中以不同的顺序进行处理,因此提供的函数的正确性不应取决于任何排序,也不应依赖于可能瞬时变化的任何其他对象或值计算进行中; 除了每一个行动,理想情况下都是无副作用的。 对Map.Entry对象的批量操作不支持方法setValue 。

    forEach:对每个元素执行给定的操作。 变量形式在执行操作之前对每个元素应用给定的变换。search:返回在每个元素上应用给定函数的第一个可用非空结果; 当找到结果时跳过进一步的搜索。reduce:累积每个元素。 提供的减少功能不能依赖于排序(更正式地,它应该是关联和交换)。 有五种变体: 平原减少 (由于没有相应的返回类型,因此(key,value)函数参数没有这种方法的形式)映射的减少积累了应用于每个元素的给定函数的结果。使用给定的基础值减少到标量双,长和int。

     这些批量操作接受一个parallelismThreshold参数。 如果估计当前地图大小小于给定阈值,则方法依次进行。 使用Long.MAX_VALUE的值Long.MAX_VALUE抑制所有的并行性。 使用1的值可以通过划分为足够的子任务来完全利用用于所有并行计算的ForkJoinPool.commonPool()来实现最大并行度。 通常,您最初将选择其中一个极值,然后测量使用中间值之间的性能,从而降低开销与吞吐量之间的关系。

    批量操作的并发属性遵循ConcurrentHashMap的并发属性:从get(key)返回的任何非空结果和相关的访问方法与相关的插入或更新都有一个发生之前的关系。 任何批量操作的结果都反映了这些每个元素关系的组成(但是除非以某种方式已知是静态的,它们并不一定是相对于整个地图的原子)。 相反,因为映射中的键和值从不为空,所以null作为目前缺乏任何结果的可靠原子指标。 为了保持此属性,null用作所有非标量缩减操作的隐含基础。 对于double,long和int版本,基础应该是当与任何其他值组合时返回其他值(更正式地,它应该是减少的标识元素)。 大多数常见的减少具有这些属性; 例如,使用基数0或最小值与基准MAX_VALUE计算和。

    作为参数提供的搜索和转换函数应该类似地返回null以指示缺少任何结果(在这种情况下不被使用)。 在映射缩减的情况下,这也使得转换可以用作过滤器,如果不应该组合元素,返回null(或者在原始专业化的情况下,身份基础)。 在使用它们进行搜索或减少操作之前,您可以通过在“null意味着现在没有任何内容”规则下自行构建复合转换和过滤。

    接受和/或返回Entry参数的方法维护键值关联。 例如,当找到最大价值的钥匙时,它们可能是有用的。 请注意,可以使用new AbstractMap.SimpleEntry(k,v)提供“plain”Entry new AbstractMap.SimpleEntry(k,v) 。

    批量操作可能突然完成,抛出在应用程序中遇到的异常。 在处理这样的异常时,请注意,其他并发执行的函数也可能引发异常,或者如果没有发生第一个异常,则会这样做。

    与顺序形式相比,加速比是常见的,但不能保证。 如果并行计算的基础工作比计算本身更昂贵,则涉及小地图上的简短功能的并行操作可能比顺序形式执行得更慢。 类似地,如果所有处理器正忙于执行不相关的任务,并行化可能不会导致太多的实际并行。

    所有任务方法的所有参数都必须为非空值。

    构造方法

    构造方法和描述ConcurrentHashMap()

    创建一个新的,空的地图与默认的初始表大小(16)。

    ConcurrentHashMap(int initialCapacity)

    创建一个新的空的地图,其初始表格大小适应指定数量的元素,而不需要动态调整大小。

    ConcurrentHashMap(int initialCapacity, float loadFactor)

    根据给定的元素数量( initialCapacity )和初始表密度( loadFactor ),创建一个新的,空的地图,初始的表格大小。

    ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel)

    创建具有基于给定数量的元件(初始表大小的新的空映射 initialCapacity ),表密度( loadFactor ),和同时更新线程(数 concurrencyLevel )。

    ConcurrentHashMap(Map<? extends K,? extends V> m)

    创建与给定地图相同的映射的新地图。

    方法

    类型和参数方法和描述voidclear()

    从这张地图中删除所有的映射。

    Vcompute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

    尝试计算用于指定键和其当前映射的值的映射(或 null如果没有当前映射)。

    VcomputeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)

    如果指定的键尚未与值相关联,则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非 null 。

    VcomputeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

    如果存在指定键的值,则尝试计算给出键的新映射及其当前映射值。

    booleancontains(Object value)

    传统方法测试如果一些键映射到此表中的指定值。

    booleancontainsKey(Object key)

    测试此表中的指定对象是否为键。

    booleancontainsValue(Object value)

    如果此映射将一个或多个键映射到指定的值,则返回 true 。

    Enumeration<V>elements()

    返回此表中值的枚举。

    Set<Map.Entry<K,V>>entrySet()

    返回此地图中包含的映射的Set视图。

    booleanequals(Object o)

    将指定的对象与此映射进行比较以获得相等性。

    voidforEach(BiConsumer<? super K,? super V> action)

    对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。

    voidforEach(long parallelismThreshold, BiConsumer<? super K,? super V> action)

    对每个(键,值)执行给定的动作。

    <U> voidforEach(long parallelismThreshold, BiFunction<? super K,? super V,? extends U> transformer, Consumer<? super U> action)

    对每个(key,value)的每个非空变换执行给定的动作。

    voidforEachEntry(long parallelismThreshold, Consumer<? super Map.Entry<K,V>> action)

    对每个条目执行给定的操作。

    <U> voidforEachEntry(long parallelismThreshold, Function<Map.Entry<K,V>,? extends U> transformer, Consumer<? super U> action)

    对每个条目的每个非空变换执行给定的操作。

    voidforEachKey(long parallelismThreshold, Consumer<? super K> action)

    对每个键执行给定的动作。

    <U> voidforEachKey(long parallelismThreshold, Function<? super K,? extends U> transformer, Consumer<? super U> action)

    对每个键的每个非空变换执行给定的动作。

    voidforEachValue(long parallelismThreshold, Consumer<? super V> action)

    对每个值执行给定的操作。

    <U> voidforEachValue(long parallelismThreshold, Function<? super V,? extends U> transformer, Consumer<? super U> action)

    对每个值的每个非空转换执行给定的动作。

    Vget(Object key)

    返回到指定键所映射的值,或 null如果此映射包含该键的映射。

    VgetOrDefault(Object key, V defaultValue)

    返回指定键映射到的值,如果此映射不包含该键的映射,则返回给定的默认值。

    inthashCode()

    返回此Map的哈希代码值,即映射中每个键值对的总和,即key.hashCode() ^ value.hashCode() 。

    booleanisEmpty()

    如果此地图不包含键值映射,则返回 true 。

    Enumeration<K>keys()

    返回此表中键的枚举。

    ConcurrentHashMap.KeySetView<K,V>keySet()

    返回此地图中包含的键的Set视图。

    ConcurrentHashMap.KeySetView<K,V>keySet(V mappedValue)

    返回此地图中键的Set视图,使用给定的公用映射值进行任何添加(即Collection.add(E)和Collection.addAll(Collection) )。

    longmappingCount()

    返回映射数。

    Vmerge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)

    如果指定的键尚未与(非空)值相关联,则将其与给定值相关联。

    static <K> ConcurrentHashMap.KeySetView<K,Boolean>newKeySet()

    创建一个新的Set支持的ConcurrentHashMap从给定的类型到Boolean.TRUE 。

    static <K> ConcurrentHashMap.KeySetView<K,Boolean>newKeySet(int initialCapacity)

    创建一个新的Set支持的ConcurrentHashMap从给定的类型到Boolean.TRUE 。

    Vput(K key, V value)

    将指定的键映射到此表中的指定值。

    voidputAll(Map<? extends K,? extends V> m)

    将指定地图的所有映射复制到此映射。

    VputIfAbsent(K key, V value)

    如果指定的键尚未与值相关联,请将其与给定值相关联。

    <U> Ureduce(long parallelismThreshold, BiFunction<? super K,? super V,? extends U> transformer, BiFunction<? super U,? super U,? extends U> reducer)

    返回使用给定的reducer将所有(key,value)对的给定变换累加到组合值的结果,如果没有则返回null。

    Map.Entry<K,V>reduceEntries(long parallelismThreshold, BiFunction<Map.Entry<K,V>,Map.Entry<K,V>,? extends Map.Entry<K,V>> reducer)

    返回使用给定的reducer累加所有条目的结果,以组合值,如果没有则返回null。

    <U> UreduceEntries(long parallelismThreshold, Function<Map.Entry<K,V>,? extends U> transformer, BiFunction<? super U,? super U,? extends U> reducer)

    返回使用给定的reducer将所有条目的给定变换累加到组合值的结果,否则返回null。

    doublereduceEntriesToDouble(long parallelismThreshold, ToDoubleFunction<Map.Entry<K,V>> transformer, double basis, DoubleBinaryOperator reducer)

    返回使用给定的reducer累加给定变换的结果,以组合值,给定基础作为一个标识值。

    intreduceEntriesToInt(long parallelismThreshold, ToIntFunction<Map.Entry<K,V>> transformer, int basis, IntBinaryOperator reducer)

    返回使用给定的reducer累加给定变换的结果,以组合值,给定基础作为一个标识值。

    longreduceEntriesToLong(long parallelismThreshold, ToLongFunction<Map.Entry<K,V>> transformer, long basis, LongBinaryOperator reducer)

    返回使用给定的reducer累加给定变换的结果,以组合值,给定基础作为一个标识值。

    KreduceKeys(long parallelismThreshold, BiFunction<? super K,? super K,? extends K> reducer)

    返回使用给定的reducer累加所有键的结果,以组合值,如果没有则返回null。

    <U> UreduceKeys(long parallelismThreshold, Function<? super K,? extends U> transformer, BiFunction<? super U,? super U,? extends U> reducer)

    返回使用给定的reducer累加所有键的给定变换以组合值的结果,如果没有则返回null。

    doublereduceKeysToDouble(long parallelismThreshold, ToDoubleFunction<? super K> transformer, double basis, DoubleBinaryOperator reducer)

    返回使用给定的reducer累加所有键的给定变换的结果,以组合值,给定基础作为标识值。

    intreduceKeysToInt(long parallelismThreshold, ToIntFunction<? super K> transformer, int basis, IntBinaryOperator reducer)

    返回使用给定的reducer累加所有键的给定变换的结果,以组合值,给定基础作为标识值。

    longreduceKeysToLong(long parallelismThreshold, ToLongFunction<? super K> transformer, long basis, LongBinaryOperator reducer)

    返回使用给定的reducer累加所有键的给定变换的结果,以组合值,给定基础作为标识值。

    doublereduceToDouble(long parallelismThreshold, ToDoubleBiFunction<? super K,? super V> transformer, double basis, DoubleBinaryOperator reducer)

    返回使用给定的reducer将所有(key,value)对的给定变换累加到结合值的结果,给定的基数作为一个标识值。

    intreduceToInt(long parallelismThreshold, ToIntBiFunction<? super K,? super V> transformer, int basis, IntBinaryOperator reducer)

    返回使用给定的reducer将所有(key,value)对的给定变换累加到结合值的结果,给定的基数作为一个标识值。

    longreduceToLong(long parallelismThreshold, ToLongBiFunction<? super K,? super V> transformer, long basis, LongBinaryOperator reducer)

    返回使用给定的reducer将所有(key,value)对的给定变换累加到结合值的结果,给定的基数作为一个标识值。

    VreduceValues(long parallelismThreshold, BiFunction<? super V,? super V,? extends V> reducer)

    返回使用给定的reducer累加所有值的结果,以组合值,如果没有则返回null。

    <U> UreduceValues(long parallelismThreshold, Function<? super V,? extends U> transformer, BiFunction<? super U,? super U,? extends U> reducer)

    返回使用给定的reducer累加所有值的给定变换以组合值的结果,否则返回null。

    doublereduceValuesToDouble(long parallelismThreshold, ToDoubleFunction<? super V> transformer, double basis, DoubleBinaryOperator reducer)

    返回使用给定的reducer累加所有值的给定变换的结果,以组合值,给定基础作为标识值。

    intreduceValuesToInt(long parallelismThreshold, ToIntFunction<? super V> transformer, int basis, IntBinaryOperator reducer)

    返回使用给定的reducer累加所有值的给定变换的结果,以组合值,给定基础作为标识值。

    longreduceValuesToLong(long parallelismThreshold, ToLongFunction<? super V> transformer, long basis, LongBinaryOperator reducer)

    返回使用给定的reducer累加所有值的给定变换的结果,以组合值,给定基础作为标识值。

    Vremove(Object key)

    从该地图中删除键(及其对应的值)。

    booleanremove(Object key, Object value)

    仅当当前映射到给定值时才删除密钥的条目。

    Vreplace(K key, V value)

    仅当当前映射到某个值时才替换该项的条目。

    booleanreplace(K key, V oldValue, V newValue)

    仅当当前映射到给定值时才替换密钥的条目。

    voidreplaceAll(BiFunction<? super K,? super V,? extends V> function)

    将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。

    <U> Usearch(long parallelismThreshold, BiFunction<? super K,? super V,? extends U> searchFunction)

    通过在每个(键,值)上应用给定的搜索函数返回非空结果,如果没有则返回null。

    <U> UsearchEntries(long parallelismThreshold, Function<Map.Entry<K,V>,? extends U> searchFunction)

    返回一个非空结果,从每个条目应用给定的搜索函数,如果没有,则返回null。

    <U> UsearchKeys(long parallelismThreshold, Function<? super K,? extends U> searchFunction)

    返回一个非空结果,在每个键上应用给定的搜索功能,如果没有,返回null。

    <U> UsearchValues(long parallelismThreshold, Function<? super V,? extends U> searchFunction)

    返回一个非空结果,对每个值应用给定的搜索函数,如果没有,返回null。

    intsize()

    返回此地图中键值映射的数量。

    StringtoString()

    返回此地图的字符串表示形式。

    Collection<V>values()

    返回此地图中包含的值的Collection视图。

    import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; /* * CopyOnWriteArrayList/CopyOnWriteArraySet : “写入并复制” * 注意:添加操作多时,效率低,因为每次添加时都会进行复制,开销非常的大。并发迭代操作多时可以选择。 */ public class TestCopyOnWriteArrayList { public static void main(String[] args) { HelloThread ht = new HelloThread(); for (int i = 0; i < 10; i++) { new Thread(ht).start(); } } } class HelloThread implements Runnable{ // private static List<String> list = Collections.synchronizedList(new ArrayList<String>()); private static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); static{ list.add("AA"); list.add("BB"); list.add("CC"); } @Override public void run() { Iterator<String> it = list.iterator(); while(it.hasNext()){ System.out.println(it.next()); list.add("AA"); } } }

     

    最新回复(0)