2

代码:

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()){

我用谷歌搜索这个程序,我知道我可以使用 aConcurrentHashMap而不是 plain HashMap

但我想知道,为什么我使用:

new HashMap<Integer,DealCountUpdater>(dealCountMap)

为 HashMap 创建新实例,仍然抛出ConcurrentModificationException

如何通过不使用来修复它ConcurrentHashMap

感谢帮助 :)

4

2 回答 2

6

原因是这样的:

  1. 您可以通过在其构造函数中传递另一个 hashmap( H2 ) 来创建一个新的 hashmap( H1 )。
  2. 在 H1 的构造函数中,它尝试遍历 H2 的元素,以添加自身。
  3. 当步骤 2 中的迭代正在进行时,其他一些线程修改了 H2。因此ConcurrentModificationException

如何在不使用ConcurrentHashMap的情况下解决它?

  1. 做外部同步
  2. 使用此处描述的 copy-n-write 映射。

但我仍然建议使用 ConcurrentHashMap,除非你真的有你的理由。

于 2011-02-24T05:15:48.267 回答
1

当另一个线程迭代它时,您根本不能或不应该修改线程中的哈希图。在这种情况下,HashMap 迭代器将抛出 ConcurrentModificationException。这被称为迭代器的“快速失败”行为,因为它在 java 文档中明确提到。对您来说最好的解决方案是使用 ConcurrentHashMap。如果您不想使用那个,那么您必须取消多线程。正如吉姆指出的那样,如果您可以提供有关多线程的更多详细信息,那么您可能会得到更好的解决方案。另外,为什么你不想使用 ConcurrentHashMap?有什么特别的原因吗?

于 2011-02-24T04:45:42.667 回答