- - PR -
ConcurrentModificationException
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2005-01-05 15:16
500個あるLinkedHashMapのキーに対してすべてremoveを行うと
100個めくらいでjava.util.ConcurrentModificationException が発生してしまいます。 内容を見てみると同期がとれていないということだったのですが、 特にそれらしい部分がみあたりません。 他に理由はあるのでしょうか。 LinkedHashMapに対してremoveするのがまずいのでしょうか。 | ||||||||
|
投稿日時: 2005-01-05 23:52
どのような状況下でそうなっているか解らないので何ともいえませんが
LinkedHashMapの実装は同期化されていません。
マップの変更中に他のスレッドから読み取りや変更を行っていませんか? また、synchronizedを使った場合はどうなりますか? synchronized(map){ map.remove(key); } あと、すべてのキーに対してremoveするのであれば、 clear()を使ったほうが良いと思います。 | ||||||||
|
投稿日時: 2005-01-06 00:08
例えば、
Map map = Collections.synchronizedMap( new LinkedHashMap(500)); /* 何か処理をする */ Object[] keys = map.keySet().toArray(); for ( int i = 0 ; i < keys.length ; i++) { key = (Integer)keys[i]; map.remove(key); } で駄目ですか? 必ず全部消すのなら、clearが良いとは思いますけど、 もし、「消すべきマッピングはいくつかあるか分からないが、場合により、全部消すことがある」ということでしたら、clearでは解決しませんよね。 | ||||||||
|
投稿日時: 2005-01-07 00:36
APIドキュメントに(いささか解りにくい表現で)書いてある通り、
ConcurrentModificationException という例外は、Iteratorを使用している最中に、 元になるCollectionやMapを変更した際にthrowされます。 原因は大きく分けて2種類あります。 (1) 単にIteratorの使い方が間違っている。
この例の場合なら、map.remove(key) ではなくて i.remove() とすればOKです。 (もちろん、全要素をremoveしたいのであれば、map.clear()の方が適切ですが) (2) スレッド間の排他が抜けている、または適切でない。 この場合は、単にsynchronizedMapを使うだけではダメで、 Iteratorを使用している全期間を排他する必要がある点に要注意です。
|
1