Программа ConcurrentModificationException в Java-хэш-карте - PullRequest
0 голосов
/ 24 февраля 2011

код:

Map<Integer,DealCountUpdater> dealCountMap=new HashMap<Integer,DealCountUpdater>();

public void update(){
    for(Map.Entry<Integer, DealCountUpdater> e:new HashMap<Integer,DealCountUpdater>(dealCountMap).entrySet()){//line:58
        System.out.println(e.hashCode());
    }
}

когда я запускаю этот код, получаю следующее исключение:

java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
        at java.util.HashMap$EntryIterator.next(HashMap.java:834)
        at java.util.HashMap$EntryIterator.next(HashMap.java:832)
        at java.util.HashMap.putAllForCreate(HashMap.java:435)
        at java.util.HashMap.<init>(HashMap.java:225)
        at org.my.tuan.count.CountUpdater.update(CountUpdater.java:58)
        at org.my.tuan._Maintainer.run(TuanSched.java:110)

эта строка называется CountUpdater.java:58:

for(Map.Entry<Integer, DealCountUpdater> e:new HashMap<Integer,DealCountUpdater>(dealCountMap).entrySet()){

Я гуглю эту программу, я знаю, что могу использовать ConcurrentHashMap вместо простого HashMap,

но я хочу знать, почему я использую:

new HashMap<Integer,DealCountUpdater>(dealCountMap)

для создания нового экземпляра для HashMap, все равно выведите ConcurrentModificationException?

как это исправить, не используя ConcurrentHashMap?

спасибо за помощь:)

Ответы [ 2 ]

3 голосов
/ 24 февраля 2011

Причина в следующем:

  1. Вы создаете новую хэш-карту ( H1 ), передавая другую хеш-карту ( H2 ) в ее конструктор.
  2. В конструкторе fo H1 он пытается перебрать элементы H2, чтобы добавить в себя.
  3. Пока идет итерация на шаге 2, какой-то другой поток модифицирует H2.Следовательно ConcurrentModificationException .

Как решить ее без использования ConcurrentHashMap ?

  1. Сделать внешнюю синхронизацию
  2. Используйте карту копирования-записи-записи, как описано здесь .

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

1 голос
/ 24 февраля 2011

Вы просто не можете или не должны изменять хэш-карту в потоке, пока другой поток перебирает его.В таких случаях итератор HashMap генерирует исключение ConcurrentModificationException.Это называется «итеративным» поведением итераторов, как это четко указано в документации по Java.Лучшее решение для вас - использовать ConcurrentHashMap.Если вы не хотите использовать это, то вам придется покончить с многопоточностью.Как указал Джим, если вы можете дать более подробную информацию о вашей многопоточности, то вы можете найти лучшее решение.Кроме того, почему вы не хотите использовать ConcurrentHashMap?Любая конкретная причина?

...