Параллелизм Java: HashMap против ConcurrentHashMap, когда параллельные потоки удаляют только элементы - PullRequest
0 голосов
/ 25 сентября 2019

У меня есть основной поток, который создает HashMap, добавляет к нему несколько исполняемых объектов, а затем запускает каждый запускаемый (передавая HashMap каждому).Runnable удаляет свой объект с карты как раз перед завершением обработки.

Я хотел бы знать, есть ли какая-либо причина использовать ConcurrentHashMap (а не HashMap) в этом случае - единственная операцияrunnables выполняют на карте, чтобы удалить себя из нее.Есть ли соображения параллелизма, которые требуют использования ConcurrentHashMap в этом случае?

Основной поток

private final Map<Integer, Consumer> runnableMap = new HashMap<>();

Runnable runnable;

for (int i = 1; i <= NUM_RUNNABLES; i++) {
    runnable = new Consumer(i, runnableMap);
    runnableMap.put(i, runnable);
    executionContext.execute(runnable);
}

Потребитель реализует Runnable

private final Integer consumerNumber;
private final Map<Integer, Consumer> runnableMap;

public Consumer(int consumerNumber, final Map<Integer, Consumer> runnableMap){
    this.consumerNumber = consumerNumber;
    this.runnableMap = runnableMap;
}

public void run() {
    :::
    // business logic
    :::
    // Below remove is the only operation this thread executes on the map
    runnableMap.remove(consumerNumber);
}

Ответы [ 3 ]

0 голосов
/ 25 сентября 2019

Вы спрашивали о различиях между HashMap и ConcurrentHashMap, но есть дополнительная структура данных, которую следует учитывать: Hashtable.Есть различия и компромиссы для каждого.Вам нужно будет оценить, какое из них лучше всего подходит для вашего предполагаемого использования.

  • HashMap не синхронизировано, поэтому, если несколько потоков могут читать или записывать в него, ваши результаты будутбыть непредсказуемым.HashMap также допускает нулевое значение как ключ или значение.

  • Hashtable синхронизируется, не поддерживает нулевые ключи или значения.С Hashtable Javadoc :

    Hashtable синхронизируется.Если поточно-ориентированная реализация не требуется, рекомендуется использовать HashMap вместо Hashtable.Если требуется высококонкурентная реализация, ориентированная на многопотоковое исполнение, то вместо Hashtable рекомендуется использовать ConcurrentHashMap.

  • ConcurrentHashMap является поточно-ориентированным,не позволяет использовать null в качестве ключа или значения.

0 голосов
/ 25 сентября 2019

Javadoc из HashMap говорит:

Обратите внимание, что эта реализация не синхронизирована.

Еслинесколько потоков обращаются к хэш-карте одновременно, и по крайней мере один из потоков структурно модифицирует карту, она должна быть синхронизирована извне.(Структурная модификация - это любая операция, которая добавляет или удаляет одно или несколько сопоставлений; простое изменение значения, связанного с ключом, который уже содержится в экземпляре, не является структурной модификацией.) Обычно это выполняется путем синхронизации с некоторым объектом, который естественным образом инкапсулирует карту.

Как уже упоминалось выше, удаление является структурным изменением, и вы должны использовать синхронизацию.

Кроме того, в методе Hashmap removeNode() (которыйвызывается методом remove()), переменная modCount увеличивается, что отвечает за ConcurrentModificationException.Таким образом, вы можете получить это исключение, если удаляете элементы без синхронизации.

Поэтому вы должны использовать ConcurrentHashMap.

0 голосов
/ 25 сентября 2019

Если ваша причина для этого состоит в отслеживании завершения потока, почему бы не использовать CountdownLatch?Не уверен, что HashMap может иметь проблемы с параллелизмом только при удалении, я рекомендую использовать его только в том случае, если ваш код не сломается при любой возможной проблеме, или использовать ConcurrentHashMap.

...