java.util.ConcurrentModificationException no Programa Non Multithreaded
-
08-07-2019 - |
Pergunta
im Hey SO Guru ter um pedaço de um trabalho com este código
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());
}
Quando eu executar o meu programa na primeira vez que tenta executar o código que atinge este erro
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)
Tendo arregalou os olhos em torno de um pouco este parece ser um erro que normalmente acontece com as linhas por que eles tentam e acessar o mesmo recurso simultaneamente, mas isso é o que ficar me im não multithreading em todo este sistema.
Alguém pode explicar por que isso está acontecendo, ou pensar em um hack para contornar o problema
Muito obrigado ^ _ ^
Solução
Você pode modificar o Collection
subjacente da Iterator
(que está escondido no circuito for-each
).
A maneira correta de fazer isso é:
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();
}
}
Outras dicas
Você não pode usar o loop for each
se você remover coisas da coleção.
Você tem que usar um Iterator
e para remover o Iterator.remove
chamada item atual.
Caso contrário, o subjacente iterador que o para-cada loop cria para você nos bastidores não compreende como é que a coleção está atravessando está mudando, diz-lhe que ele está sendo alterado enquanto você iterar-lo.
Você tem um iterador sobre população escondida sob um loop. Você está removendo um item da população no meio do iterador de trabalho. Iterator não pode mais trabalhar, porque você mudou a coleção no meio dela iteração.
Não é relacionada com multithreading.
Uma solução pode ser copiar uma coleção. Iterar sobre os elementos de cópia e remover da coleção original.
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());
}