如何使用和设置适当的ConcurrentHashMap并发级别?

时间:2013-08-28 12:38:52

标签: java concurrency

我正在使用concurrenthashmap中的大约1000个元素。默认并发级别为16。任何人都可以帮我一些算法或因素,我可以从中确定适合我的场景的并发级别,或者并发级别以多少方式影响多线程的处理。

   ConcurrentHashMap<String, String> map=new ConcurrentHashMap<String, String>(500,1,20);             

20是我的并发级别(虚拟值)。需要高效设置

5 个答案:

答案 0 :(得分:19)

根据文件:

  

更新操作之间允许的并发性由指导     可选的concurrencyLevel构造函数参数     (默认16),,用作内部大小调整的提示。该     table在内部分区以尝试允许指示     没有争用的并发更新数。因为安置     在散列表中基本上是随机的,实际的并发性     变化。 理想情况下,您应该选择一个值来容纳尽可能多的值     线程将同时修改表。使用     比你需要的价值高得多可以浪费空间和时间,     并且显着较低的值可能导致线程争用。

所以你需要回答1个问题:

同时修改表的线程数是多少?

答案 1 :(得分:6)

Java 8:

现在ConcurrentHashMap根本不使用固定的锁定条带方案,而是使用内部同步将每个桶用作“条带”。

来自源代码:

/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
    ...
    Node<K,V> f; int n, i, fh;
    ...
    else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
    ...
       synchronized (f) {
           ...
       }
}

构造函数的参数只是将其用作文档说明的大小提示。

  

concurrencyLevel - 并发更新线程的估计数量。实现可以将此值用作大小提示。

来源:

public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel) {
    if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
        throw new IllegalArgumentException();
    if (initialCapacity < concurrencyLevel)   // Use at least as many bins
        initialCapacity = concurrencyLevel;   // as estimated threads
    long size = (long)(1.0 + (long)initialCapacity / loadFactor);
    int cap = (size >= (long)MAXIMUM_CAPACITY) ?
        MAXIMUM_CAPACITY : tableSizeFor((int)size);
    this.sizeCtl = cap;
}

所以你不需要自己考虑,ConcurrentHashMap会为你处理它。

答案 2 :(得分:2)

ConcurrentHashMap允许多个读取器同时读取而不会阻塞。这是通过基于并发级别将Map划分为不同的部分并在更新期间仅锁定Map的一部分来实现的。默认并发级别为16,因此Map分为16个部分,每个部分由不同的锁控制。这意味着,16个线程可以同时在Map上运行,直到它们在Map的不同部分上运行。这使得ConcurrentHashMap在保持线程安全不变的情况下仍然具有高性能。

答案 3 :(得分:1)

16是地图将被拆分为的默认区域数。 在读取器线程的情况下,ConcurrentHashMap完成(几乎在所有情况下)都没有锁定。 编写器线程的数量是您需要担心的事情。这个数字应该等于你拥有的地区数量。

答案 4 :(得分:0)

因此,并发级别等于写程序线程。映射也会分段,等于并发级别的值。