Java Concurrent коллекция для нескольких записей и частых чтений

Я хочу использовать карту значения ключа на основе компаратора. Это будет чтение и редкая операция записи (один раз в 3 месяца через планировщик). Первоначальная загрузка коллекции будет выполнена при запуске приложения. Также обратите внимание, что запись будет:

  • Добавить одну запись на карту
  • Не будет изменять любую существующую запись на карте.

Будет ли ConcurrentSkipListMap хорошим кандидатом для этого. Является ли операция get на этом доступе к нескольким потокам одновременно? Я ищу одновременное чтение без блокировки, но атомарную запись.

3 ответа

ConcurrentHashMap это именно то, что вы ищете. Из Javadoc:

Операции извлечения (включая get) обычно не блокируются, поэтому могут перекрываться с операциями обновления (включая put и remove). Извлечения отражают результаты самых последних завершенных операций обновления, проводимых с момента их появления. (Более формально, операция обновления для данного ключа имеет отношение "происходит до" с любым (не нулевым) поиском для этого ключа, сообщающего об обновленном значении.)

Это звучит так, как будто это удовлетворяет вашему требованию для "одновременного не блокирующего чтения, а атомарного чтения"

Так как вы делаете так мало записей, вы можете указать высокий loadFactor и соответствующий initialSize при создании ConcurrentHashMap, что предотвратит изменение размера таблицы при заполнении карты, хотя в лучшем случае это незначительное преимущество. (Вы также можете установить для параметра concurrencyLevel значение 1, хотя Javadoc в Java 8, похоже, подразумевает, что он больше не используется в качестве подсказки для определения размера.)

Если вам абсолютно необходимо иметь SortedMap или же NavigableMap, затем ConcurrentSkipListMap это готовый путь. Но я бы дважды проверил, что вам действительно нужны функциональные возможности, предоставляемые этими интерфейсами (получение первого / последнего ключа, вложенных карт, поиск соседних записей и т. Д.), Прежде чем их использовать. Вы заплатите высокую цену (log n или постоянное время для большинства операций).

Если вы хотите попробовать сторонний код, вы можете рассмотреть вариант карт с копированием при записи, которые идеально подходят для редких записей. Вот тот, который появился через Google:

https://bitbucket.org/atlassian/atlassian-util-concurrent/wiki/CopyOnWrite%20Maps

Никогда не пробовал сам так будьте бдительны.

Поскольку вы ищете параллельные операции, у вас есть в основном 3 конкурента. Hashtable, ConcurrentHashMap, ConcurrentSkipListMap (или Collections.synchronizedMap (), но это неэффективно).

  • Из этих 3 последние 2 больше подходят для одновременной работы, поскольку они просто блокируют часть карты, а не блокируют всю карту, как Hashtable.
  • Из последних 2 SkipListMap использует структуру данных списка пропусков, которая обеспечивает среднюю производительность O (log n) для быстрого поиска и различных операций.
  • Он также предлагает ряд операций, которые ConcurrentHashMap не может выполнить, например, floorEntry/Key(), floorEntry / Key () и т. Д. Он также поддерживает порядок сортировки, который в противном случае должен был бы быть рассчитан.

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

Другие вопросы по тегам