java.util.ConcurrentModificationException dans un programme non multithread
-
08-07-2019 - |
Question
Hé, SO Guru, j'ai un sacré boulot avec ce code
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());
}
Lorsque j'exécute mon programme la première fois qu'il tente d'exécuter le code, cette erreur survient
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)
Cela semble être une erreur qui survient normalement avec les threads qui tentent d’accéder simultanément à la même ressource, mais c’est ce qui fait que je ne suis pas multithread dans ce système.
Quelqu'un peut-il expliquer pourquoi cela se produit ou penser à un piratage pour le contourner
Merci beaucoup ^ _ ^
La solution
Vous pouvez modifier le Collection
sous-jacent de Iterator
(masqué dans la boucle pour chaque
).
La bonne façon de procéder est la suivante:
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();
}
}
Autres conseils
Vous ne pouvez pas utiliser le code pour chaque boucle
si vous supprimez des éléments de la collection.
Vous devez utiliser un Iterator
et supprimer l'appel d'élément actuel Iterator.remove
.
Sinon, l'itérateur sous-jacent que la boucle for-each crée pour vous en coulisse ne comprend pas pourquoi la collection en cours change, mais vous dit qu'elle est modifiée pendant que vous la répétez.
Vous avez un itérateur sur la population caché sous une boucle for. Vous supprimez un élément de la population au milieu d'un itérateur en cours d'utilisation. Iterator ne peut plus fonctionner car vous avez modifié la collection au milieu de son itération.
Cela n’est pas lié au multithreading.
Une solution de contournement peut être de copier une collection. Parcourez la copie et supprimez des éléments de la collection d'origine.
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());
}