2

構造の同時ハッシュマップを使用しています

Map<Set<Date>, Map<String, Object>> SampleMap

指定されたマップ ( Map<String, Object>) 内で使用される Map も並行ハッシュマップですが、セットは唯一のTreeSetタイプです。

それでも、ログに次の行を追加すると、同時変更例外が発生します。

logger.debug("sampleMap.keySet() + ". Size is " + sampleMap.keySet().size()"); 

また、このマップを扱う同じクラスの他の部分でも。

このマップは、複数のスレッドによるバッチ処理で広く使用され、マップに値を挿入および削除します。使用される Java バージョンは 1.5 です。

例外は Treeset によるものだと思います。また、タイプ Set の同時処理コレクションの同様の実装がないこともわかりました。

与えられた問題に対する私の考えが正しいかどうかを確認し、この問題の解決策を提案していただければ幸いです。

4

1 に答える 1

3

キーを「変更」できる必要があるため、このパターンに従う必要があります

// lock the collection
Map<String, Object> values = map.remove(key);
key = new TreeSet<String>(key);
// modify copy of key
map.put(key, values);
// unlock the collection.

ConcurrentMap がサポートしていない操作を実行しているため、独自のロックを使用する必要があります。プレーンな HashMap または LinkedHashMap を synchronized または ReentrantReadWriteLock で使用できます。


を使用して同時セットを作成できます

// Added in Java 1.6
Set<String> set = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
// or to be sorted
Set<String> set = Collections.newSetFromMap(new ConcurrentSkipListMap<String, Boolean>());

ただし、キーの内容を変更することはできないため、使用する必要があるのは

Set<String> key = Collections.unmodifiableSet(treeSet);
// or to be sure its not modified
Set<String> key = Collections.unmodifiableSet(new TreeSet<String>(treeSet));

Map でキーを使用した後にキーを変更できない理由の簡単な例。

Set<String> key1 = new TreeSet<String>();
Map<Set<String>, Boolean> map = new ConcurrentHashMap<Set<String>, Boolean>();
map.put(key1, true);
System.out.println("Is the map ok? "+map.containsKey(key1));
key1.add("hello");
System.out.println("Is the map ok? "+map.containsKey(key1));

版画

Is the map ok? true
Is the map ok? false

一般的な動作は、マップ内のキーが見えなくなることです。これは、マップが hashCode に基づいてキーをバケットに配置するためです。hashCode が変更された場合、間違ったバケットにある可能性があるため、検索しても見つかりません。

于 2012-09-10T11:32:35.977 に答える