Foro de elhacker.net

Programación => Java => Mensaje iniciado por: w00t; en 10 Diciembre 2009, 15:22 pm



Título: ConcurrentModificationException
Publicado por: w00t; en 10 Diciembre 2009, 15:22 pm
Bueno estoy teniendo un problema al modifcar una lista, me está tirando un error de concurrencia (java.util.ConcurrentModificationException)

El bloque de código que genera problema, es el siguiente

Código
  1. if(celdaAux.getMalos()!= null && celdaAux.getFuego() == true){
  2. for(Malo m : celdaAux.getMalos()){
  3. m.matar(getBomberman(1));
  4. celdaAux.removeMalo(m);
  5. celdaAux.setfueModificada(true);
  6. }
  7.  
  8.  

Investigué un poco, y encontré que el problema se da por que estoy eliminando elementos de una lista mientras estoy iterando sobre la misma.
Una solución a esto es usando el remove del iterador. No me funcionó
Y otra usando un bloque syncronized(){...}, pero no sé como aplicarlo


Título: Re: ConcurrentModificationException
Publicado por: Casidiablo en 10 Diciembre 2009, 16:20 pm
Como bien dices, puedes usar syncronized bien sea en cada método en donde accedas a la lista o creando un bloque dentro del método. Aquí tienes una explicación:

http://epere4.blogspot.com/2008/04/cmo-funciona-synchronized-en-java.html

Un saludo!


Título: Re: ConcurrentModificationException
Publicado por: w00t; en 10 Diciembre 2009, 18:48 pm
He leído lo que me dejaste, pero sigo sin poder solucionar el problema.

La excepción que se produce es la siguiente

Código:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at juego.Nivel.checkColisiones(Nivel.java:164)
at frontend.GUI_Principal.chekearColisiones(GUI_Principal.java:341)
at frontend.GUI_Principal.game(GUI_Principal.java:325)
at frontend.GUI_Principal.main(GUI_Principal.java:346)

Por esto entiendo que, cuando la clase Nivel quiso acceder al método checkColisiones() se produjo el error por que ya había un objeto GUI_Principal, accediendo a este por medio de la llamada chekearColisiones().

Como debería aplicar el syncronized? Destaco que nivel, no tiene una referencia al unico objeto del tipo GUI_Principal que hay en ejecución


Título: Re: ConcurrentModificationException
Publicado por: Leyer en 10 Diciembre 2009, 20:28 pm
es complicado ayududate sin el code completo prueba syncronizando el metodo o el obj de class que llamas para el metodo checkColisiones() y si esta en un hilo recuerda syncronizar el metodo run

SL2



Título: Re: ConcurrentModificationException
Publicado por: w00t; en 10 Diciembre 2009, 23:47 pm
Sinceramente estoy estancado, no encuentro solución. He puesto y sacado syncronized por todos lados ya ^^

Pongo los fragamentos de código de las clases involucradas en el error, no pongo las clases completas por que son cientos de líneas.  No quería recurrir a esto de ponerles el código ya que el trabajo de debuggear es mío, pero ya estoy frustado xD

El error
Código:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at juego.Nivel.checkColisiones(Nivel.java:165)
at frontend.GUI_Principal.chekearColisiones(GUI_Principal.java:396)
at frontend.GUI_Principal.game(GUI_Principal.java:378)
at frontend.GUI_Principal.main(GUI_Principal.java:401)

Ahora el codigo de clases, les marco las lineas q indica el error
Código
  1.  
  2. public class Nivel {
  3. protected java.util.LinkedList<Malo> cMalos;
  4.  
  5. /**
  6. * Retorna la lista de malos del nivel
  7. * @return
  8. */
  9. public LinkedList<Malo> getMalos(){
  10. return cMalos;
  11. }
  12.  
  13.  
  14. /**
  15. * Retorna la celda x,y
  16. * @param x
  17. * @param y
  18. * @return
  19. */
  20. public Celda getCelda(int x, int y)
  21. {
  22. return tablero[x][y];
  23. }
  24.  
  25. /**
  26. * Chekea colisiones en la celda (x,y)
  27. * @param x
  28. * @param y
  29. */
  30. public void checkColisiones(int x, int y) {
  31. Celda celdaAux = getCelda(x,y);
  32.  
  33.  
  34. //Colsion Malo - Fuego
  35. //(LINEA 165)
  36.                 if(celdaAux.getMalos()!= null && celdaAux.getFuego() == true){
  37. for(Malo m : celdaAux.getMalos()){
  38. m.matar(getBomberman(1));
  39. celdaAux.removeMalo(m);
  40. celdaAux.setfueModificada(true);
  41. }
  42. }
  43.       }
  44.  
  45.  
  46. }
  47.  

Código
  1. public class GUI_Principal extends Canvas implements KeyListener{
  2.  
  3. /**
  4. * Ciclo del juego
  5. */
  6. public void game() {
  7. Graphics g = this.getGraphics();
  8. inicializar();
  9. //Input de teclado
  10. addKeyListener(this);
  11. timer.start();
  12. while (isVisible() && !b.getMurio()) {
  13. chekearColisiones();
  14. paintTablero();
  15. jLabel2.setText(Integer.toString(b.getScore()));
  16. jLabel4.setText(timer.getResult());
  17. g.drawImage(buffer, 0, 0, this);
  18. try {
  19. Thread.sleep(b.getVel());
  20. } catch (InterruptedException e) {}
  21. }
  22. System.out.println("te moriste pete");
  23. }
  24.  
  25. /**
  26. * Chekea las colisiones en todas las celdas de la matriz
  27. */
  28. private  void chekearColisiones() {
  29. for(int i=0;i<n.matriz_width;i++)
  30. for(int j=0;j<n.matriz_height;j++)
  31. //LINEA 396
  32.                                 n.checkColisiones(i, j);
  33. }
  34.  
  35. public static void main(String[] args) {
  36. GUI_Principal gui = new GUI_Principal();
  37. gui.game();
  38. }
  39. }
  40.  


Título: Re: ConcurrentModificationException
Publicado por: Leyer en 11 Diciembre 2009, 00:28 am
mm pero no veo que nivel este llamando este llamando a checkColisiones()..  bueno si dices que colocaste syncronized por todos lados jeje bueno  intenta esto cuando la class  nivel intente acceder checkColisiones() coloca un wait anterior a las sentencias dond se llama al metodo checkColisiones() en la gui entonces cuando el nivel termine de hacer su "tarea" con el checkColisiones() notificas el la gui para que esta continue..

Saludos.


Título: Re: ConcurrentModificationException
Publicado por: w00t; en 11 Diciembre 2009, 00:46 am
El unico que llama a checkColisiones() es GUI_Principal. Nivel nunca lo llama

Creo q  el error se produce por que cuando checkColisiones esta recorriendo/modificando la lista cMalos, hay otro hilo que la esta iterando. Puede ser?


Título: Re: ConcurrentModificationException
Publicado por: w00t; en 11 Diciembre 2009, 01:06 am
Si el problema era ese, encontré la solución acá:

http://www.coderanch.com/t/233932/Threads-Synchronization/java/deal-with-Concurrent-Modification-Exception

http://www.javalobby.org/java/forums/t76297.html

Seguí esos tips y funcionó todo correctamente!

Estaba usando bien el syncronized, pero tenia que eliminar con el remove del iterador ademas de sincronizarlo.

Desde ya, gracias por la ayuda L-EYER y Casidiablo.