Как сделать доступ к значению в Java Hashmap синхронизированы? - PullRequest
0 голосов
/ 29 февраля 2020

Допустим, у меня есть Java Hashmap, где ключи являются строками или чем-то еще, а значения являются списками других значений, например

Map<String,List<String>> myMap=new HashMap<String,List<String>>();
//adding value to it would look like this
myMap.put("catKey", new ArrayList<String>(){{add("catValue1");}} );

Если у нас много потоков, добавляющих и удаляющих значения из списки (не меняя ключи только значения Hashmap) есть ли способ сделать доступ к спискам только потокобезопасным? чтобы многие потоки могли редактировать много значений одновременно?

Ответы [ 3 ]

1 голос
/ 29 февраля 2020

Использовать реализацию синхронизированного или одновременного списка вместо ArrayList, например

Последний не список, но полезен, если вам на самом деле не нужен доступ -by-index (т. е. произвольный доступ), поскольку он работает лучше, чем другие.


Обратите внимание, поскольку вам, вероятно, потребуется одновременная вставка исходного пустого списка в карту для нового ключа, вам следует используйте ConcurrentHashMap для самого Map вместо простого HashMap.


Рекомендация

Map<String, Deque<String>> myMap = new ConcurrentHashMap<>();

// Add new key/value pair
String key = "catKey";
String value = "catValue1";
myMap.computeIfAbsent(key, k -> new ConcurrentLinkedDeque<>()).add(value);

Приведенный выше код является полностью поточно-ориентированным при добавлении нового ключа на карту и полностью поточно-ориентированным при добавлении нового значения в список. Код не тратит время на получение блокировок синхронизации и не испытывает ухудшения, которое имеет CopyOnWriteArrayList при увеличении списка.

Единственная проблема заключается в том, что он использует Deque, а не List, но реальность такова, что в большинстве случаев List можно с легкостью использовать Deque, но указывается List по привычке, так что это, вероятно, приемлемое изменение.

1 голос
/ 29 февраля 2020

Во-первых, используйте параллельную карту ha sh, которая будет синхронизировать этот конкретный сегмент.

Во-вторых, необходимо использовать функции atomi c, в противном случае, когда один поток будет использовать метод get, другой поток может вызвать put метод. Как ниже

// wrong 
if(myMap.get("catKey") == null){
    myMap.put("catKey",new ArrayList<String>(){{add("catValue1");}});       
}

//correct
myMap.compute("catKey", (key, value) -> if(value==null){return new ArrayList<String>(){{add("catValue1");}}} return value;);
1 голос
/ 29 февраля 2020

Существует класс ConcurrentHashMap, который реализует ConcurrentMap, который можно использовать для обработки потоков Map. compute, putIfAbsent, merge, все потоки безопасно обрабатывают несколько вещей, пытаясь воздействовать на одно и то же значение одновременно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...