Domanda

Hey SO Guru, sto avendo un diavolo di lavoro con questo codice

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 eseguo il mio programma la prima volta che tenta di eseguire il codice, viene visualizzato questo errore

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)

Avendo gorgogliato un po 'questo sembra essere un errore che si verifica normalmente con i thread perché provano ad accedere alla stessa risorsa contemporaneamente, ma questo è ciò che mi fa non essere affatto multithreading in questo sistema.

Qualcuno può spiegare perché questo sta accadendo o pensare a un hack per aggirarlo

Mille grazie ^ _ ^

È stato utile?

Soluzione

Puoi modificare la Collection sottostante di Iterator (che è nascosta nel ciclo per ogni ). Il modo corretto per farlo è:

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

Altri suggerimenti

Non puoi usare il per ogni ciclo se rimuovi oggetti dalla collezione.
Devi usare un Iterator e per rimuovere la voce dell'elemento corrente Iterator.remove .

Altrimenti, l'iteratore sottostante che il ciclo for-each crea per te dietro le quinte non capisce come sta cambiando la collezione che sta attraversando, ti dice che sta cambiando mentre lo fai.

Hai un iteratore sulla popolazione nascosto in un ciclo for. Stai rimuovendo un oggetto dalla popolazione durante il funzionamento dell'iteratore. Iterator non può più funzionare perché hai cambiato la raccolta nel mezzo di iterazione.

Non è legato al multithreading.

Una soluzione alternativa può essere la copia di una raccolta. Scorri sulla copia e rimuovi gli elementi dalla raccolta originale.

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

}

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top