Подтвердить что ты не робот

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)

Немного поразмыслив, кажется, что это ошибка, которая обычно происходит с потоками, почему они пытаются одновременно получить доступ к одному и тому же ресурсу, но это то, что заставляет меня не многопоточать в этой системе.

Может кто-нибудь объяснить, почему это происходит, или подумать о взломе, чтобы обойти его.

Большое спасибо ^ _ ^

4b9b3361

Ответ 1

Вы можете изменить базовый 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();
    }
}

Ответ 2

Вы не можете использовать цикл for each, если вы удаляете вещи из коллекции.
Вы должны использовать Iterator и удалить текущий вызов элемента Iterator.remove.

В противном случае базовый итератор, созданный для каждого цикла для вас за кулисами, не понимает, как происходит изменение коллекции, говорит вам, что она изменяется во время ее повторения.

Ответ 3

У вас есть итератор над населением, скрытый под циклом for. Вы удаляете элемент из совокупности в середине работы итератора. Итератор не может работать больше, потому что вы изменили коллекцию в середине ее итерации.

Это не относится к многопоточности.

Ответ 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());

}