Как использовать и установить соответствующий уровень concurrency для ConcurrentHashMap?

Я работаю с примерно 1000 элементами в concurrenthashmap. Значение по умолчанию concurrency равно 16. может ли кто-нибудь помочь мне с некоторым алгоритмом или факторами, из которых я могу определить уровень concurrency, подходящий для моего сценария, или каким образом уровень concurrency влияет на обработку нескольких потоков.

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

20 - мой уровень concurrency (фиктивное значение). Нужно установить это эффективно

Ответы

Ответ 1

Согласно документам:

Допустимый concurrency среди операций обновления управляется   необязательный аргумент конструктора concurrencyLevel  (по умолчанию 16), , который используется как подсказка для внутреннего размера.   таблица внутренне разделена, чтобы попытаться разрешить указанные   количество одновременных обновлений без конкуренции. Поскольку размещение   в хэш-таблицах по существу случайный, фактический concurrency будет   меняются. В идеале вы должны выбрать значение для размещения как можно большего количества   нити, которые когда-либо будут одновременно изменять таблицу..   значительно более высокое значение, чем вам нужно, может тратить пространство и время,   и значительно меньшее значение может привести к конфликту с потоком.

Итак, вам нужно ответить на один вопрос:

Каково количество потоков, которые когда-либо будут одновременно изменять таблицу?

Ответ 2

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) {
           ...
       }
}

И конструктор имеет параметр, который просто использует его как подсказку размера, как говорят docs.

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 будет обрабатывать его для вас.

Ответ 3

ConcurrentHashMap позволяет считывать несколько считывателей одновременно без блокировки. Это достигается путем разбиения карты на разные части на основе уровня concurrency и блокировки только части Карты во время обновлений. Уровень по умолчанию concurrency равен 16, и, соответственно, карта разделяется на 16 частей, и каждая часть управляется с помощью другой блокировки. Это означает, что 16 потоков могут работать на карте одновременно, пока они не будут работать на другой части Карты. Это делает ConcurrentHashMap высокой производительностью, несмотря на то, что безопасность потоков не повреждена.

Ответ 4

16 - это число регионов по умолчанию, в которое будет разбита ваша карта. ConcurrentHashMap, в случае потоков читателей, выполняется (почти во всех случаях) без блокировки вообще. Число потоков писателей - это то, о чем вам нужно беспокоиться. И это число должно быть равно количеству регионов, которые у вас есть.

Ответ 5

Таким образом, уровень параллелизма равен потоку писателя. И карта также будет сегментирована равной значению уровня параллелизма.