14

インスタンスを返す関数を呼び出しています。TreeMap呼び出し元のコードで、を変更したいと思いましたTreeMap。しかし、私はを取得していConcurrentModificationExceptionます。

これが私のコードです:

public Map<String, String> function1() {
    Map<String, String> key_values = Collections.synchronizedMap(new TreeMap<String, String>());
    // all key_values.put() goes here

    return key_values;
}

そして私の呼び出しコードは次のとおりです。

Map<String, String> key_values =Collections.synchronizedMap(Classname.function1());
//here key_values.put() giving ConcurrentModificationException
4

5 に答える 5

16

イテレータを使用している場合、同時変更から保護されることCollections.synchronizedMap決してないことに注意してください。Mapさらに、複数のスレッドからアクセスしている場合を除いて、同期マップを作成しても意味がありません。他のスレッドに渡されていないローカルスコープのコレクションと変数は、である必要はありませんsynchronized

私の推測では、省略したコードでは、、、、またはのいずれかを反復処理し、Map.entrySetそのMap.keySet反復中に(ループ内で呼び出しMap.valuesています。あなたが示したコードでは、これがこれが起こり得る唯一の方法です。put for

于 2012-12-18T06:47:29.030 に答える
7

ConcurrentSkipListMapを使用すると、より高速になる可能性があり、この問題は発生しません。

public NavigableMap<String, String> function1() {
    NavigableMap<String, String> key_values = new ConcurrentSkipListMap<String, String>();
    // all key_values.put() goes here

    return key_values;
}

キーを並べ替える必要がない場合は、ConcurrentHashMapを使用できます。

于 2012-12-18T09:40:14.567 に答える
1

同期されたMAPを探しているので、マルチスレッドアプリを扱っていると思います。その場合、イテレータを使用する場合は、MAPのブロックを同期する必要があります。

/*This reference will give error if you update the map after synchronizing values.*/
    Map<String, String> values =Collections.synchronizedMap(function1());

/*This reference will not give error if you update the map after synchronizing values  */
        Map<String, String> values = Collections.synchronizedMap(new TreeMap<String, String>());


     synchronized (values) 
                {           
                    Iterator it = values.entrySet().iterator();
                    while(it.hasNext())
                    {
                        it.next() ; 
    // You can update the map here.     
                    }
                }

アップデート :

実際の場合、MAPを2回ラップしているというエラーを考慮すると、同期されたブロックでもwhileループで変更すると、更新されている元のMAPオブジェクトで同期できないため、CM例外が発生します。

于 2012-12-18T07:10:21.390 に答える
1

同期マップの同期マップを取得しているようです。function1()の呼び出しをその内容(簡略化)に置き換えると、次のようになります。

Map<String, String> key_values =Collections.synchronizedMap(Collections.synchronizedMap( new TreeMap<String, String>()));

私はあなたのコーリングラインを次のように変更する必要があると思います:

Map<String, String> key_values = Classname.function1();
于 2012-12-18T06:49:12.620 に答える
0

これは私がそれを上げてやっていたことですConcurrentModificationException

TreeMap<Integer, Integer> map = new TreeMap<>();

for (Integer i : map.keySet()) {
    map.remove(i)
}

これは、例外を修正するために同じ機能に対して行ったことです。

TreeMap<Integer, Integer> map = new TreeMap<>();

// I would not recommend this in production as it will create multiple
// copies of map
for (Integer i : new HashMap<>(integers).keySet()) {
    map.remove(i)
}
于 2020-05-30T18:12:36.597 に答える