1

HashMapIDと名前のペアを格納するがあります。このマップの各エントリについて、条件付きで、別のに配置しHashMapます。最後に、2番目のマップエントリを使用していくつかの操作を実行します。このコードはすべてJSPファイルで記述されています。

シングルユーザーリクエストの場合、これは正常に機能しています。一度に複数のユーザーがこのファイルにアクセスしようとすると、1つの要求のみが成功し、他のユーザーでも同じ結果になります。

ログに次の例外が表示されます。

org.apache.jasper.JasperException: java.util.ConcurrentModificationException

マップはこの形式です

Map<String, String> testmap= new HashMap<String, String>();
4

4 に答える 4

2

java.util.HashMapのJavaドキュメントから:

このクラスのすべての「コレクション ビュー メソッド」によって返される反復子はフェイルファストです。反復子の作成後に、反復子自身の remove メソッド以外の方法でマップが構造的に変更された場合、反復子は ConcurrentModificationException をスローします。 . したがって、同時変更に直面した場合、反復子は、将来の不確定な時点で恣意的で非決定論的な動作を危険にさらすのではなく、迅速かつ明確に失敗します。

すでに提案されているように、最も簡単な解決策は、Map同時に反復/変更される へのアクセスを同期することです。

Map map = ... //the map object has to be the same for all users calling your jsp

synchronized(map) {
   //do work
}

並行性については、Oracle Java チュートリアルも参照してください。

于 2012-09-23T17:46:38.603 に答える
1

マップが多くのスレッドによって同時にアクセスおよび変更される場合は、問題に対してより適切なマップ実装を使用してみてください: ConcurrentHashMap コレクションがそのトリックを実行できます。

final Map<String,String> map = new ConcurrentHashMap<String,String>();

Java 5 を使用できない場合:

final Map map = Collections.synchronizedMap(new HashMap());
于 2012-09-25T15:20:03.947 に答える
0

その場合、おそらく異なるリクエストが異なるスレッドで実行されます。共通のデータ構造テストマップで同期する必要があります。

これを達成する方法はいくつかあります。@Tudorはロックを提案します。それが1つの可能な方法です。これが演習である場合は、一般的なマルチスレッドでの同期とsynchronizedJavaでのメソッドについて何かを読むことをお勧めします。

于 2012-09-23T17:45:38.470 に答える
0

コレクションを反復処理しているときにコレクションを変更すると、同じスレッドから発生した場合でも、複数のスレッドから同時に発生した場合でも、このエラーが発生します。私の疑惑は、それが複数のユーザー要求で発生するため、2番目のケースであるということです。アクセスをロックで保護するようにしてください(おそらく、マップオブジェクトごとに1つのロック)。

于 2012-09-23T17:46:03.673 に答える