java.util.Исключение ConcurrentModificationException в программе, не являющейся многопоточной
-
08-07-2019 - |
Вопрос
Эй, так у меня, Гуру, чертовски сложная работа с этим кодом
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)
Немного поразмыслив, кажется, что это ошибка, которая обычно возникает с потоками, почему они пытаются получить доступ к одному и тому же ресурсу одновременно, но это то, что заставляет меня вообще не заниматься многопоточностью в этой системе.
Кто-нибудь может объяснить, почему это происходит, или придумать способ обойти это
Большое спасибо ^_^
Решение
Вы можете изменить базовый 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();
}
}
Другие советы
Вы не можете использовать для каждого цикла
, если удаляете вещи из коллекции.
Вы должны использовать Iterator
и удалить текущий вызов элемента Iterator.remove
.
В противном случае основной итератор, который цикл for-each создает для вас за кулисами, не понимает, почему происходит изменение коллекции, через которую он проходит, сообщает, что она изменяется, пока вы выполняете итерацию. Р>
У вас есть итератор для заполнения, скрытый под циклом for. Вы удаляете элемент из популяции во время работы итератора. Итератор больше не может работать, потому что вы изменили коллекцию во время итерации.
Это не связано с многопоточностью.
Обходным решением может быть копирование коллекции.Выполните итерацию по копии и удалите элементы из исходной коллекции.
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());
}