2011-12-20 1 views
0

私は全体のプログラムのすべてのメソッドを同期させたにもかかわらず、ConcurrentModificationExceptionを取得します(静的メソッドとmainメソッドを含む)。プログラムのすべてのメソッドが同期されているときにConcurrentModificationExceptionが発生する可能性はありますか?

私はイテレータを隠していません。

  1. これはどのように可能ですか?
  2. どういう意味ですか?
  3. どうすれば修正できますか?
+0

私はそれについて何かについてのいくつかの推測を持っていますが、完全なトレースバックは便利です。 –

答えて

6
  1. その上を反復しながら、 ConcurrentModificationExceptionそれはそれらを反復処理しながら、 Iterator.remove()または ListIterator.add()方法
  2. を参照してくださいを通じて以外、コレクションを変更しないことを意味コレクションを操作同じスレッドが原因で発生することができ2.
3

この例外は、コレクションを反復処理しているときに、このコレクションからエントリを削除するときに発生します。

Collection<Object> objects = new ArrayList<Objects>(Arrays.asList("a","b")); 
for (Object o : objects) { 
    objects.remove(o); //throws exception 
} 

削除するアイテムを別のコレクションに追加して、リストの完成した反復処理後に削除する必要があります。 それ以外の場合は、iterator()を使用してオブジェクトコレクションを反復処理し、現在のイテレータでremove()を呼び出します。

+0

なぜそれが起こるはずですか? –

+0

コレクションのremove()はそれを検索し、以前のイテレータを無効にします。 このケースを処理するには十分スマートではないと思うので、例外がスローされます。 これは他の人よりも良い答えです。 – Steven

3

ConcurrentModificationExceptionは同期に関連していません。

コレクションの反復処理中にコレクションを変更することに関連しています。 Lie Ryanが指摘するように、完全なスタックトレースは、あなたがどのようにそれを得たかを指摘するのに役立ちます。

一般的に、これを修正するには、反復処理中にコレクション自体を変更しないでください。

+1

コレクションの反復処理中にコレクションを変更すると何が問題になりますか?どのように避けることができますか? –

+0

何が問題なのは、イテレータが壊れる可能性があるということです。したがって、反復中に基礎となるコレクションを変更したことが検出された場合、ほとんどのイテレータはこのエラーをスローするようになります。それを避けることができます....それをしないでください。申し訳ありませんが、正確にあなたがしたことについての詳細がなければ、私はより具体的にすることはできません。 – rfeak

+0

私の勘違いは、あなたがループしてそれを取り除こうとしているときに、複数のイテレータが演奏されていることです。 – Steven

3

あなたはこの

List<Object> list = new ArrayList<Object>(); 
for(Object obj : list) 
    list.remove(obj); 

を実行する場合は、コモディティ化を取得します。コレクションを反復処理している間は、適切な関数を使用せずにコレクションを変更することはできません。あなたはそれを見ているならば、それが可能だ、

まあ
List<Object> list = new ArrayList<Object>(); 
for(Iterator<Object> itr = list.iterator(); itr.hasNext();) 
    itr.remove(); 
3

、で開始する:

これは、以下のものを使用して解決することができる鳥の本と鳥は鳥を信じて、反対している場合。

どうしたらできますか?コードを見ずに正確に言うのは難しいですが、例外スタックトレースは発生した場所を指します。その周りには何が見えますか?

一般に、明らかに並行アクセスがあると起こります。それが起こっている場所を見つけたら、そこにどのスレッドが到達しているのか自分自身に尋ねます。

1

synchronizedメソッドは、実行中のオブジェクトインスタンスにロックを設定します。

オブジェクトAとBが同じコレクションにアクセスする場合、A#doStuffとB#doStuffが同期しているかどうかは関係ありませんが、それらは同時に実行できます。

コレクションをロックするには、メソッド本体のsynchronized(コレクション)またはJava 5ミューテックス(より良い方法)のコレクション自体をロックすることが必要です。

(他の人が指摘しているように、単一のスレッドでもConcurrentModificationExceptionを持つことができます)。

1

ConcurrentModificationExceptionのjavadocは、答えが含まれています

この例外は、オブジェクトが異なるスレッドスレッドによって同時に変更されたことを必ずしも示すとは限りません。 1つのスレッドがオブジェクトの契約に違反する一連のメソッド呼び出しを発行すると、オブジェクトはこの例外をスローする可能性があります。たとえば、スレッドがフェイル・ファースト・イテレータを使用してコレクションを反復している間に、スレッドがコレクションを直接変更した場合、イテレータはこの例外をスローします。

これを修正する方法はありません。イテレータを同時に変更するのではなく、イテレータによって提供されたメソッドを使用して、反復と変更を同時に行う必要がある場合は、(他にも記載されているように)

関連する問題