2009-11-29 11 views
15

अरे अतः गुरु की im इस कोडjava.util.ConcurrentModificationException कार्यक्रम

public void kill(double GrowthRate, int Death) 
{ 
    int before = population.size(); 
    for (PopulationMember p : population) 
    { 
     int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness()); 
     if (probs[RandomNumberGen.nextRandomInt(0, 99)]==0) 
     { 
      population.remove(p); 
     } 
    } 
    System.out.println("Intial Population: "+before+", Deaths:"+(before-   population.size())+", New Population: "+population.size()); 
} 

जब मैं अपने कार्यक्रम के लिए पहली बार यह कोड को चलाने के लिए कोशिश करता है चलाने के साथ एक नौकरी की एक बिल्ली होने यह इस त्रुटि हिट

Exception in thread "main" java.util.ConcurrentModificationException 
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) 
    at java.util.HashMap$KeyIterator.next(HashMap.java:828) 
    at Genetics.Population.kill(Population.java:181) 
    at Genetics.Population.run(Population.java:47) 
    at Control.Main.main(Main.java:35) 

एक सा ऐसा गलती से हुआ है कि सामान्य रूप से धागे कारण है कि वे कोशिश करते हैं और समवर्ती एक ही संसाधन का उपयोग के साथ होता है प्रतीत हो रहा है चारों ओर goggled करने के बाद, लेकिन यह मुझे क्या im इस प्रणाली में बिल्कुल भी multithreading नहीं मिल रहा है।

कोई व्याख्या कर सकते हैं क्यों यह हो रहा है, या एक हैक के लगता है कि यह चारों ओर

बहुत धन्यवाद प्राप्त करने के लिए^_^

उत्तर

41

आप Iterator के अंतर्निहित Collection को संशोधित कर सकते हैं (जो for-each लूप में छिपा हुआ है)। यह करने के लिए उचित तरीका है:

for (Iterator<PopulationMember> it = population.iterator(); it.hasNext();) { 
    PopulationMemeber p = it.next(); 
    int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness()); 
    if (probs[RandomNumberGen.nextRandomInt(0, 99)] == 0) { 
     it.remove(); 
    } 
} 
+0

धन्यवाद इस कोड को मेरे कोड का एक बड़ा हिस्सा मिला है – Gwilym

12

आप for each पाश उपयोग नहीं कर सकते यदि आप संग्रह से चीजों को हटा दें।
आपको Iterator का उपयोग करना होगा और वर्तमान आइटम कॉल Iterator.remove को निकालना होगा।

अन्यथा, अंतर्निहित पुनरावर्तक जो प्रत्येक लूप आपके लिए दृश्यों के पीछे बनाता है, यह समझ में नहीं आता है कि यह संग्रह कैसे बदल रहा है, यह बताता है कि इसे बदलने के दौरान इसे बदला जा रहा है।

+0

धन्यवाद इस भावना – Gwilym

+0

इटरेटर के न की बहुत जरूरी इस पद्धति को लागू करना आसान हो गया है (http://java.sun.com/javase/6/docs/api/java/util/ प्रति Iterator.html # निकालें% 28% 29)। –

+0

@ कालेब - इस मामले में किसी को पुनरावृत्ति के दौरान चीजों को नहीं हटाया जाना चाहिए। – abyx

8

आपके पास लूप के नीचे छिपी हुई आबादी पर एक इटरेटर है। आप आइटरेटर के बीच में आबादी से एक वस्तु को हटा रहे हैं। इटरेटर अब और काम नहीं कर सकता क्योंकि आपने इसे बीच में संग्रह को बदल दिया है।

यह मल्टीथ्रेडिंग से संबंधित नहीं है।

+0

बहुत धन्यवाद – Gwilym

4

का संभावित हल एक संग्रह कॉपी किया जा सकता है। प्रतिलिपि पर Iterate और मूल संग्रह से तत्वों को हटा दें।

public void kill(double GrowthRate, int Death) { 
    int before = population.size(); 
    Collection<PopulationMember> forIteration = new HashSet<PopulationMember>(population); 
    for (PopulationMember p : forIteration) { 
     int[] probs = ProbablityArrayDeath(GrowthRate,Death,(int)p.fitness()); 
     if (probs[RandomNumberGen.nextRandomInt(0, 99)]==0) { 
      population.remove(p); 
     } 
    } 
    System.out.println("Intial Population: "+before+", Deaths:"+(before - population.size())+", New Population: "+population.size()); 

}

+2

यह काम करता है जब आप किसी कारण से iterator.remove() को आसानी से कॉल नहीं कर सकते हैं। –

संबंधित मुद्दे