私は2つのスレッドでプログラムを書いています。1つは循環リンクリストを反復することです。リンクリストは循環型であるため、リストには常に次の要素があります。リストを変更する別のスレッド。しかし、concurrentModificationExceptionが発生します。私はそれで何ができますか?ありがとう
3 に答える
次のAPIドキュメントから:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/ConcurrentModificationException.html
この例外は、オブジェクトの同時変更が許可されていない場合に、そのような変更を検出したメソッドによってスローされる可能性があります。
たとえば、別のスレッドがコレクションを反復処理しているときに、あるスレッドがコレクションを変更することは一般的に許可されていません。一般に、これらの状況では、反復の結果は定義されていません。一部のIterator実装(JREによって提供されるすべての汎用コレクション実装の実装を含む)は、この動作が検出された場合にこの例外をスローすることを選択する場合があります。これを行うイテレータは、将来の不確定な時点で任意の非決定論的な動作のリスクを冒すのではなく、迅速かつクリーンに失敗するため、フェイルファストイテレータと呼ばれます。
この例外は、オブジェクトが別のスレッドによって同時に変更されたことを常に示しているわけではないことに注意してください。単一のスレッドがオブジェクトのコントラクトに違反する一連のメソッド呼び出しを発行した場合、オブジェクトはこの例外をスローする可能性があります。たとえば、スレッドがフェイルファストイテレータを使用してコレクションを反復処理しているときにコレクションを直接変更すると、イテレータはこの例外をスローします。
この場合、例外が発生するのでイテレータを使用しないでください。
単に設定するcurrentElement = currentElement.next()
か、(無限?)ループで呼び出されるものを使用して、現在の要素を進めます。
リストがスレッドセーフでない場合、データ構造を同時に変更するときに問題が発生する可能性があります。
実装がスレッドセーフであると仮定すると(どのクラスを使用していますか?)、イテレーターは本質的にスレッドセーフではありません。彼らはリストをロックしていないので、他のスレッドがリストを変更するのを防ぐことはできません。
CircularListがそれ自体で同期する場合(使用しているものはわかりませんが、スレッドセーフリストでは一般的です。そうでない場合、イテレータは基本的に常に非スレッドセーフになります)、次のようにしてこれを回避できます。
synchronized(list) {
Iterator i = list.iterator();
doSomething(i);
}