2014-11-27 5 views
0

Приведенный ниже код получает одновременное изменение версии, когда 2 потока доступа одинаковы.ConcurrentModifcationException при добавлении значения в hashmap

Я хотел бы знать, является ли

  1. ли это исключение можно избежать, если использовать параллельный HashMap.
  2. Если мы используем одновременный hashmap, будет какая-либо проблема в многопоточной среде.

или есть ли другой способ предотвратить это исключение?

Я не намерен использовать синхронизацию, поскольку этот код используется во время опроса. поскольку одному потоку, возможно, придется подождать, пока другой закончит экзекуцию.

Код

HashMap<Integer, myModel> aServiceHash = new HashMap<Integer, myModel>(); 
HashMap<Integer, myModel> rServiceHash = new HashMap<Integer, myModel>(); 

for (myModel ser : serAccepted){ 
    aServiceHash.put(service.getOriginalDate(), ser); 
} 
for (myModel ser : serRequested) { 
    if (aServiceHash.containsKey(service.getDate())) { 
     aServiceHash.put(serv.getDate(), serv); 
    } 
    else 
     rServiceHash.put(service.getDate(), ser); 
} 

Приглашение http://examples.javacodegeeks.com/java-basics/exceptions/java-util-concurrentmodificationexception-how-to-handle-concurrent-modification-exception/

http://www.journaldev.com/378/how-to-avoid-concurrentmodificationexception-when-using-an-iterator

How to avoid HashMap "ConcurrentModificationException" while manipulating `values()` and `put()` in concurrent threads?

Использование JSF 2.1, 7.1 JDK.

ответ

1

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

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

Другой способ предотвратить исключение - заблокировать карту перед каждой вставкой, будь то через синхронизированный блок или объект Lock.

+0

Если поток хочет что-то удалить, должен ли я использовать итератор? –

+0

'ConcurrentHashMap' должно быть хорошо, даже если поток просто использует' remove() '. Конечно, вам понадобится итератор, если это нам, пока вы зацикливаетесь на элементах карты –

1

В зависимости от ваших шаблонов использования и требований к производительности вы также можете создать карту копирования на запись, используя делегат volatileHashMap. Это даст вам одно volatile read для каждого доступа, тогда как в ConcurrentHashMap у вас будет намного больше, и они немного дороже обычного чтения или записи. Конечно, схемы копирования на запись имеют свои недостатки, когда вы пишете на карте. Но если вы создадите карту из предварительно заполненной исходной карты и считаете ее доступной только для чтения, копирование по-записи будет более эффективным.