2012-12-18 27 views
7

मैं फ़ंक्शन कॉल कर रहा हूं जो TreeMap उदाहरण देता है, और कॉलिंग कोड में मैं TreeMap को संशोधित करना चाहता था। हालांकि, मुझे ConcurrentModificationException मिल रहा है।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 
+1

क्या मैं function1 के भीतर से सिंक्रनाइज़ किए गए मानचित्र बनाने के बिंदु से पूछ सकता हूं? इसका उपयोग किसी के द्वारा नहीं किया जा रहा है लेकिन आपका "कॉलिंग कोड" ... –

+0

आप मानचित्र को कैसे संशोधित करते हैं? –

उत्तर

2

यदि आप 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 उपयोग कर सकते हैं।

+1

यह समझने में उपयोगी हो सकता है कि * स्किप सूची * क्या है: https://en.wikipedia.org/wiki/Skip_list –

13

ध्यान दें कि Collections.synchronizedMapआप एक iterator उपयोग कर रहे हैं समवर्ती संशोधन से बचाने के लिए कभी नहीं होगा। इसके अतिरिक्त, जब तक आप एक से अधिक धागे से अपने Map तक पहुंच नहीं ले रहे हैं, तो सिंक्रनाइज़ नक्शा बनाना बेकार है। स्थानीय रूप से-स्कोप्ड संग्रह और चर जो अन्य धागे को सौंपे नहीं जा रहे हैं उन्हें synchronized होने की आवश्यकता नहीं है।

मेरा अनुमान है कि कोड आप बाहर छोड़ दिया, आप Map.entrySet में से एक, Map.keySet, या Map.values से अधिक पुनरावृत्ति कर रहे हैं, और कि यात्रा (for पाश के अंदर) के दौरान putबुला है। आपके द्वारा दिखाए गए कोड के साथ, यह एकमात्र तरीका हो सकता है।

+0

हां आप लिखते हैं महोदय, यह मेरी गलती थी .. धन्यवाद –

1

आपको सिंक्रनाइज़ किए गए मानचित्र का सिंक्रनाइज़ नक्शा मिल रहा है। अगर मैं() function1 करने के लिए कॉल एक यह की सामग्री के साथ (सरलीकृत) की जगह हमने:

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

मुझे लगता है कि आपके फोन करने के लाइन के लिए बदला जाना चाहिए:

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

वास्तव में कोई जवाब नहीं है, इसलिए कोई +1 नहीं, लेकिन फिर भी एक अच्छा नोट है। – Brian

+0

@ ब्रायन मुझे लगता है कि यह विवरण महत्वपूर्ण है। चूंकि, इस डबल रैप के साथ वह वास्तविक TreeMap ऑब्जेक्ट पर सिंक्रनाइज़ नहीं कर पाएगा, जिसकी आवश्यकता होगी यदि वह इटरेट करने और अपडेट करने का प्रयास करता है। –

1

आप एक तुल्यकालन एमएपी के लिए देख रहे हैं , इसलिए मुझे लगता है कि आप एक बहुप्रचारित ऐप से निपट रहे हैं। उस स्थिति में यदि आप इटरेटर का उपयोग करना चाहते हैं, तो आपको एमएपी के लिए ब्लॉक सिंक्रनाइज़ करना होगा।

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

अद्यतन:

अपने मामले में वास्तव में

, अं है कि आप दो बार एमएपी लपेटकर कर रहे हैं पर विचार है, जबकि पाश में इसे संशोधित भी एक तुल्यकालन ब्लॉक के साथ एक मुख्यमंत्री अपवाद आप होगा के रूप में दे देंगे मूल एमएपी ऑब्जेक्ट पर सिंक्रनाइज़ करने में सक्षम नहीं है जो उबला हुआ हो रहा है।