ConcurrentModificationException は、許可されていないときにオブジェクトを同時に変更しようとすると発生します。この例外は通常、次の操作を行っているときに発生します。 Java コレクション クラス 。
例えば - 他のスレッドがコレクションを反復しているときに、スレッドがコレクションを変更することは許可されません。これは、反復の結果が未定義になるためです。 JRE によって提供される Iterator の汎用実装をすべて含む、Iterator クラスの一部の実装は、この例外をスローします。これを行うイテレータは次のように呼ばれます フェイルファスト 将来的にコレクションの不確定な動作に直面するのではなく、そのような状況に遭遇するとすぐに例外をスローするためです。
Android携帯電話の設定メニュー
注記:他のスレッドが Collection オブジェクトを変更しようとした場合にのみこの例外がスローされることは必須ではありません。また、単一のスレッドに、オブジェクトのコントラクトに違反しようとするいくつかのメソッドが呼び出された場合にも発生する可能性があります。これは、スレッドが何らかの反復処理中に Collection オブジェクトを変更しようとしているときに発生することがあります。フェイルファスト反復子の場合、イテレータは例外をスローします。
例
import java.awt.List; import java.util.*; public class Concurrentmodificationexception { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); Iterator it = list.iterator(); while (it.hasNext()) { Integer value = it.next(); System.out.println('List Value:' + value); if (value.equals(3)) list.remove(value); } } }
出力:
このメッセージは、反復子がリストを反復し、同時にリストの変更を行っているため、次のメソッドが呼び出されたときに例外がスローされることを示しています。ただし、以下に示すようにハッシュマップに変更を加えた場合、ハッシュマップのサイズは変わらないため、そのような例外はスローされません。
データ構造内の構造
例えば-
import java.awt.List; import java.util.*; public class concurrentmodificationexception { public static void main(String[] args) { HashMap map = new HashMap(); map.put(1, 1); map.put(2, 2); map.put(3,3); Iterator it = map.keySet().iterator(); while(it.hasNext()) { Integer key = it.next(); System.out.println('Map Value:' + map.get(key)); if (key.equals(2)) { map.put(1, 4); } } } }
出力:
Map Value:1 Map Value:2 Map Value:3
この例は、イテレータがマップを反復している間、マップのサイズが変化しないため、完全に正常に動作します。では地図のみが更新されています if ステートメント 。
ConcurrentModificationException のコンストラクター
ConcurrentModificationExceptionのコンストラクタは4種類あります。
Javaでのデザインパターン
- public ConcurrentModificationException() -
これにより、パラメーターのない ConcurrentModificationException が作成されます。 - public ConcurrentModificationException(文字列メッセージ)
これにより、例外を指定する詳細メッセージを含む ConcurrentModificationException が作成されます。 - public ConcurrentModificationException(スロー可能な原因)
これにより、原因とメッセージ (cause==null?null:cause.toString()) を含む ConcurrentModificationException が作成されます。原因は後で Throwable.getCause() によって取得されます。 - public ConcurrentModificationException(文字列メッセージ、スロー可能な原因)
これにより、詳細なメッセージと原因を含む ConcurrentModificationException が作成されます。 (cause==null?null:cause.toString())。メッセージは後で Throwable.getMessage() によって取得され、原因は後で Throwable.getCause() によって取得されます。
マルチスレッド環境で ConcurrentModificationException を回避するにはどうすればよいですか?
マルチスレッド環境で ConcurrentModificationException を回避するには、次の方法に従います。
- コレクション クラスを反復処理する代わりに、配列を反復処理できます。この方法では、小さいサイズのリストをうまく処理できますが、配列のサイズが非常に大きい場合はパフォーマンスが低下します。
- もう 1 つの方法は、リストを同期ブロックに入れてロックすることです。これによってマルチスレッドを使用する唯一の目的が放棄されるため、これは効果的なアプローチではありません。
- JDK 1.5 以降では、ConcurrentHashMap クラスと CopyOnWriteArrayList クラスが提供されます。これらのクラスは、同時変更例外を回避するのに役立ちます。
シングルスレッド環境で ConcurrentModificationException を回避するにはどうすればよいですか?
イテレータのremove()関数を使用すると、基礎となるコレクションオブジェクトからオブジェクトを削除できます。