スレッドの例外 'Thread-2' java.util.ConcurrentModificationException



Exception Threadthread 2java



現在、コレクションで反復を実行すると、既存のオブジェクトを判断して削除するときにエラーとして報告されます。

変更前:



Iterator it=draw.getFoes().iterator() while(it.hasNext()){ Foe foe=it.next() if(foe.getX()==shot.getX()&&foe.getY()==shot.getY()){ draw.getFoes().remove(foe) draw.getShots().remove(shot) System.out.println('shooting the enemy') } }

変更後

Iterator it=draw.getFoes().iterator() while(it.hasNext()){ Foe foe=it.next() if(foe.getX()==shot.getX()&&foe.getY()==shot.getY()){ // draw.getFoes().remove(foe) it.remove() draw.getShots().remove(shot) System.out.println('shooting the enemy') } }

後で私はインターネット上で見るべき情報を見つけました:



フェイルファストイテレータを使用してコレクションまたはマップの反復中にコレクション/マップのコンテンツを直接変更しようとすると、単一のスレッドで実行されている場合でもjava.util.ConcurrentModificationExceptionがスローされます。イテレータは別のスレッドで動作しており、ミューテックスロックがあります。 Iteratorが作成されると、元のオブジェクトを指すシングルチェーンインデックステーブルが作成されます。元のオブジェクト数が変更されても、インデックステーブルの内容は同期的に変更されないため、インデックスポインタが後方に移動すると、インデックステーブルが見つかりません。オブジェクトなので、フェイルファストの原則に従って、イテレータはすぐにjava.util.ConcurrentModificationExceptionをスローします。

したがって、イテレータが機能しているときは、反復オブジェクトによる変更は許可されていません。ただし、Iterator独自のメソッドremove()を使用してオブジェクトを削除することができ、Iterator.remove()メソッドは、現在の反復オブジェクトを削除する間、インデックスの一貫性を維持します。

興味深いのは、Collection / Mapオブジェクトに実際に要素が1つしかない場合、ConcurrentModificationExceptionがスローされないことです。これが、その正確性をこの例外に依存するプログラムを作成することが間違っている理由です。ConcurrentModificationExceptionは、バグを検出するためにのみ使用する必要があります。



変更後:it.remove()