2009-11-29 45 views
15

喂有這麼一個工作赫克這個代碼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()); 
} 

當我運行我的程序嘗試運行該代碼的第一次大師的IM它擊中這個錯誤

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) 

已經瞪大眼睛張望了一下,這似乎是通常與線程爲什麼他們試圖同時訪問相同的資源發生了錯誤,但是這是他們讓我在即時通訊這個系統不是多線程的。

有人可以解釋爲什麼發生這種情況,還是覺得一個黑客繞過它

非常感謝^ _^

回答

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 2009-11-29 18:04:42

12

您不能使用for each循環,如果你從集合中刪除的東西。
您必須使用Iterator並刪除當前項目調用Iterator.remove

否則,for-each循環在幕後爲您創建的基礎迭代器不理解它所經歷的集合如何變化,告訴您在迭代它時正在更改它。

+0

感謝這使得SENCE – Gwilym 2009-11-29 17:56:14

+0

迭代器不要的很多一定要實現這個方法(每http://java.sun.com/javase/6/docs/api/java/util/ Iterator.html#刪除%28%29)。 – 2009-11-29 17:56:25

+0

@Kaleb - 在這種情況下,在迭代期間不應該刪除東西。 – abyx 2009-11-29 17:57:45

8

你已經有了一個隱藏在for循環下的迭代器。 您正在從迭代器工作中的人口中刪除項目。 迭代器無法正常工作,因爲您在迭代過程中更改了集合。

這與多線程無關。

+0

非常感謝,因爲 – Gwilym 2009-11-29 17:56:54

4

一種解決方法可以是複製的集合。迭代副本並從原始集合中刪除元素。

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()出於某種原因。 – 2011-05-16 14:45:38