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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1816196/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:55:23  来源:igfitidea点击:

java.util.ConcurrentModificationException in Non Multithreaded Program

javamultithreadingcollectionsjava.util.concurrent

提问by Gwilym

Hey SO Guru's im having one heck of a job with this code

嘿,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());
}

When I run my program the first time it tries to run the code it hits this error

当我第一次运行我的程序时,它尝试运行代码时遇到此错误

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)

Having goggled around a bit this seems to be an error that normally happens with threads why they try and access the same resource concurrently, but this is what getting me im not multithreading at all in this system.

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

Can someone explain why this is happening, or think of a hack to get around it

有人可以解释为什么会发生这种情况,或者想办法绕过它

Many thanks ^_^

非常感谢^_^

采纳答案by Bozho

You can modify the underlying Collectionof the Iterator(which is hidden in the for-eachloop). The proper way to do this is:

您可以修改底层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();
    }
}

回答by abyx

You can't use the for eachloop if you remove things from the collection.
You have to use an Iteratorand to remove the current item call Iterator.remove.

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

Otherwise, the underlying iterator that the for-each loop creates for you behind the scenes doesn't understand how come the collection it's going through is changing, tells you that it is being changed while you iterate it.

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

回答by Yoni Roit

You've got an iterator over population hidden under a for loop. You are removing an item from population in the middle of iterator working. Iterator can't work no more because you changed the collection in the middle of it iterating.

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

It's not related to multithreading.

它与多线程无关。

回答by Eugene Platonov

A workaround can be copy a collection. Iterate over the copy and remove elements from the original collection.

解决方法可以是复制集合。迭代副本并从原始集合中删除元素。

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());

}

}