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

ConcurrentHashMap私はこのプログラムをグーグルで検索します、私はプレーンの代わりに使用できることを知っていますHashMap

しかし、私は知りたいのですが、なぜ私は:を使用しています

new HashMap<Integer,DealCountUpdater>(dealCountMap)

HashMapの新しいインスタンスを作成するには、それでもスローしConcurrentModificationExceptionますか?

使用しないで修正する方法はConcurrentHashMap

手伝ってくれてありがとう :)

4

2 に答える 2

6

理由はこれです:

  1. コンストラクターで別のハッシュマップ( H2 )を渡すことにより、新しいハッシュマップ(H1 )を作成します。
  2. H1のコンストラクターでは、H2の要素を反復処理して、それ自体を追加しようとします。
  3. 手順2の反復が行われている間、他のスレッドがH2を変更します。したがって、ConcurrentModificationException

ConcurrentHashMapを使用せずにそれを解決する方法は?

  1. 外部同期を行う
  2. ここで説明するように、コピーアンドライトマップを使用します。

ただし、本当に理由がない限り、ConcurrentHashMapを使用することをお勧めします。

于 2011-02-24T05:15:48.267 に答える
1

別のスレッドがハッシュマップを反復処理している間は、スレッド内のハッシュマップを変更することはできません。このような場合、HashMapイテレーターはConcurrentModificationExceptionをスローします。これは、Javaドキュメントで明確に言及されているため、イテレータの「フェイルファスト」動作と呼ばれます。最善の解決策は、ConcurrentHashMapを使用することです。それを使用したくない場合は、マルチスレッドを廃止する必要があります。jimが指摘したように、マルチスレッドに関する詳細を提供できれば、より良い解決策が得られる可能性があります。また、なぜConcurrentHashMapを使用したくないのですか?何か特別な理由はありますか?

于 2011-02-24T04:45:42.667 に答える