2012-12-18 18 views
7

TreeMap örneğini döndüren ve arama kodunda TreeMap numarasını değiştirmek istediğim işlevi çağırıyorum. Ancak, ConcurrentModificationException alıyorum.TreeMap ConcurrentModificationException'ı Önleme

İşte benim kodudur:

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; 
} 

Ve çağıran kodunuz: Bir yineleyici kullanıyorsanız Collections.synchronizedMapeşzamanlı değişiklik sizi korumak asla edeceğini

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

Senkronize Harita Oluşturma noktasını function1 içinden sorabilir miyim? Bu, hiç kimse tarafından kullanılmıyor, ancak "arama kodunuz" ... –

+0

Haritayı nasıl değiştiriyorsunuz? –

cevap

2

ConcurrentSkipListMap kullanırsanız, daha hızlı olabilir ve bu sorun yok.

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

    return key_values; 
} 

anahtarları gerekmiyorsa

bir ConcurrentHashMap kullanabilirsiniz sıralanmasını.

+1

Bir atlama listesinin * ne olduğunu anlamak faydalı olabilir: https://en.wikipedia.org/wiki/Skip_list –

13

Not. Buna ek olarak, Map numaranıza birden fazla iş parçacığından erişmiyorsanız, senkronize edilmiş haritayı oluşturmak işe yaramaz. Yerel olarak izlenen koleksiyonlar ve diğer iş parçacıklarına teslim edilmeyen değişkenlerin synchronized olması gerekmez.

Benim tahminim dışında kalan kodunda, sen Map.entrySet birine Map.keySet veya Map.values üzerinde yineleme demektir ve (for döngü içinde) o yineleme sırasında putarayarak olmasıdır. Gösterdiğiniz kodla, bunun gerçekleşmesi için tek yol budur.

+0

Yazıyorsunuz efendim, bu benim hatamdı .. Teşekkürler –

1

Senkronize edilmiş bir haritanın senkronize edilmiş bir haritasını alıyor gibi görünüyorsunuz. Ben (basitleştirilmiş) bir otel olduğu bir içeriği ile function1 çağrısı() değiştirirseniz biz var: Bir senkronize MAP arıyoruz

Map<String, String> key_values = Classname.function1(); 
+1

Gerçekten bir cevap değil, bu yüzden +1, ama yine de iyi bir not. – Brian

+0

@Brian Bu detayın önemli olduğunu düşünüyorum. Çünkü, bu çift sargı ile, yinelemeye ve güncellemeye çalışırsa ihtiyaç duyacağı gerçek TreeMap nesnesini senkronize edemez. –

1

:

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

Ben senin arayan hattın şekilde değiştirilmelidir düşünüyorum Bu yüzden çok iş parçacıklı bir uygulama ile uğraştığınızı farz ediyorum. Bu durumda yineleyici kullanmak istiyorsanız, MAP için senkronize edilmiş bir blok oluşturmalısınız.

/*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.  
        } 
       } 

Güncelleme:

sizin durumunuzda Aslında

, yaptığınız gibi bir CM İstisna verecek hatta senkronize blokla süre döngü içinde değiştirerek, iki kez MAP sarmalıyor err dikkate udpated olan orijinal MAP nesnesinde senkronize edilemez.