2009-11-29 11 views
15

Hey así que estoy de Guru tener un gran trabajo con este códigojava.util.ConcurrentModificationException en No multiproceso Programa

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

Cuando ejecuto mi programa la primera vez que intenta ejecutar el código que llegue a este error

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) 

Habiendo Goggled todo un poco esto parece ser un error que suele ocurrir con las roscas por qué tratar de acceder a los mismos recursos al mismo tiempo, pero esto es lo que yo im conseguir no multithreading en absoluto en este sistema.

¿Puede alguien explicar por qué ocurre esto, o pensar en un truco para conseguir alrededor de él

Muchas gracias^_^

Respuesta

41

Puede modificar el Collection subyacente del Iterator (que está oculto en el bucle for-each). La forma correcta de hacerlo es:

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

gracias esto tiene una gran parte de mi código en funcionamiento – Gwilym

12

No se puede utilizar el bucle for each si se quita cosas de la colección.
Tiene que usar un Iterator y para eliminar el elemento actual llame al Iterator.remove.

De lo contrario, el iterador subyacente que el bucle for-each crea para usted detrás de las escenas no entiende cómo está cambiando la colección que está atravesando, le dice que se está modificando mientras lo itera.

+0

gracias esto hace que una gran cantidad de Dont SENCE – Gwilym

+0

de iterador necesariamente tiene que poner en práctica este método (por http://java.sun.com/javase/6/docs/api/java/util/ Iterator.html # remove% 28% 29). –

+0

@Kaleb - en cuyo caso uno no debería eliminar cosas durante la iteración. – abyx

8

Tiene un iterador sobre la población oculta en un ciclo for. Está eliminando un elemento de la población en el medio del trabajo del iterador. Iterator no puede funcionar más porque ha cambiado la colección en el medio de la iteración.

No está relacionado con el multihilo.

+0

muchas gracias también – Gwilym

4

Una solución puede ser distribuido, copiado de una colección. Itera sobre la copia y elimina elementos de la colección 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()); 

}

+2

Esto funciona cuando no se puede invocar fácilmente iterator.remove() por alguna razón. –

Cuestiones relacionadas