15

嘿 SO Guru 我正在用这段代码做一份工作

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)

仔细观察了一下,这似乎是线程通常会发生的错误,为什么它们会尝试同时访问相同的资源,但这就是让我在这个系统中根本不使用多线程的原因。

有人可以解释为什么会这样,或者想办法绕过它

非常感谢^_^

4

4 回答 4

41

您可以修改底层CollectionIterator隐藏在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();
    }
}
于 2009-11-29T17:56:14.763 回答
12

for each如果从集合中删除东西,则不能使用循环。
您必须使用Iteratorand 来删除当前项目调用Iterator.remove

否则,for-each 循环在幕后为您创建的底层迭代器不了解它所经历的集合是如何发生变化的,它会告诉您在迭代时它正在发生变化。

于 2009-11-29T17:53:43.673 回答
8

你有一个隐藏在 for 循环下的人口迭代器。您正在迭代器工作的中间从人口中删除一个项目。迭代器不能再工作了,因为你在它迭代的过程中改变了集合。

它与多线程无关。

于 2009-11-29T17:54:31.977 回答
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());

}

于 2010-11-26T18:10:46.130 回答