Java 如何为 ConcurrentHashMap 使用和设置适当的并发级别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18488163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use and set appropriately concurrency level for ConcurrentHashMap?
提问by csk
I am working with around 1000 elements in concurrenthashmap . Default concurrency level is 16 . can anyone help me with some algorithm or factors from which i can identify the concurrency level suitable for my scenario or in what way a concurrency level affects the processing of multiple threads .
我正在使用 concurrenthashmap 中的大约 1000 个元素。默认并发级别为 16 。谁能帮我一些算法或因素,从中我可以确定适合我的场景的并发级别或并发级别以何种方式影响多线程的处理。
ConcurrentHashMap<String, String> map=new ConcurrentHashMap<String, String>(500,1,20);
20 is my concurrency level (dummy value) .Need to set this efficiently
20 是我的并发级别(虚拟值)。需要有效地设置它
采纳答案by Tala
According to docs:
根据文档:
The allowed concurrency among update operations is guided by the optional
concurrencyLevel
constructor argument (default16
), which is used as a hint for internal sizing. The table is internally partitioned to try to permit the indicated number of concurrent updates without contention. Because placement in hash tables is essentially random, the actual concurrency will vary.Ideally, you should choose a value to accommodate as many threads as will ever concurrently modify the table.Using a significantly higher value than you need can waste space and time, and a significantly lower value can lead to thread contention.
更新操作之间允许的并发性由可选的
concurrencyLevel
构造函数参数 (default16
)指导,该参数用作内部大小的提示。该表在内部进行了分区,以尝试允许指定数量的并发更新而不会发生争用。因为散列表中的放置本质上是随机的,所以实际的并发性会有所不同。理想情况下,您应该选择一个值来容纳尽可能多的线程同时修改表。使用明显高于您需要的值会浪费空间和时间,而明显较低的值会导致线程争用。
So you need to answer 1 question:
所以你需要回答1个问题:
What is the number of threads that will ever concurrently modify the table?
将同时修改表的线程数是多少?
回答by Eugene
16 is the default number of regions that your map will be split into. ConcurrentHashMap, in case of reader threads, is done (in almost all cases) without locking at all. The number of writer threadsis the thing you need to worry. And this number should be equal to the number of regions you have.
16 是您的地图将被分割成的默认区域数。ConcurrentHashMap,在读者线程的情况下,是在没有锁定的情况下完成的(几乎在所有情况下)。编写线程的数量是您需要担心的事情。这个数字应该等于你拥有的区域数量。
回答by sagar baviskar
ConcurrentHashMap allows multiple readers to read concurrently without any blocking. This is achieved by partitioning Map into different parts based on concurrency level and locking only a portion of Map during updates. Default concurrency level is 16, and accordingly Map is divided into 16 part and each part is governed with different lock. This means, 16 thread can operate on Map simultaneously, until they are operating on different part of Map. This makes ConcurrentHashMap high performance despite keeping thread-safety intact.
ConcurrentHashMap 允许多个读者并发读取而不会发生任何阻塞。这是通过基于并发级别将 Map 划分为不同部分并在更新期间仅锁定 Map 的一部分来实现的。默认并发级别为 16,因此 Map 分为 16 部分,每个部分使用不同的锁进行管理。这意味着,16 个线程可以同时操作 Map,直到它们操作 Map 的不同部分。尽管保持线程安全完整,这使得 ConcurrentHashMap 具有高性能。
回答by Tony
Java 8:
爪哇 8:
Now the ConcurrentHashMap
does not use a fixed lock striping scheme at all, instead each bucket serves as a “stripe” using intrinsic synchronization.
现在ConcurrentHashMap
根本不使用固定的锁条带化方案,而是使用内在同步将每个桶用作“条带”。
Code from source:
源代码:
/** 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) {
...
}
}
And the constructor has the parameter just use it as a size hint as docs say.
并且构造函数的参数只是将其用作文档所说的大小提示。
concurrencyLevel - the estimated number of concurrently updating threads. The implementation may use this value as a sizing hint.
concurrencyLevel - 估计的并发更新线程数。实现可以使用这个值作为调整大小的提示。
And the source:
和来源:
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;
}
So you don't need to consider it by yourself, ConcurrentHashMap
will handle it for you.
所以你不需要自己考虑,ConcurrentHashMap
会为你处理。
回答by harit
So,concurrency level is the equal to to the writer threads.And map will also segmented equals to the value of concurrency level.
因此,并发级别等于写入线程。并且映射也将分段等于并发级别的值。