非多线程程序中的java.util.ConcurrentModificationException

时间:2009-11-29 17:52:28

标签: java multithreading collections java.util.concurrent

嘿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 个答案:

答案 0 :(得分:41)

您可以修改Collection的基础Iterator(隐藏在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();
    }
}

答案 1 :(得分:12)

如果从集合中删除内容,则无法使用for each循环 您必须使用Iterator并删除当前的项目调用Iterator.remove

否则,for-each循环在幕后为你创建的底层迭代器不会理解它正在经历的集合是如何变化的,它告诉你在迭代它时它正在被更改。

答案 2 :(得分:8)

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

它与多线程无关。

答案 3 :(得分: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());

}

相关问题