8 Replies Latest reply: Jun 21, 2007 11:53 AM by 807605 RSS

    ConcurrentModificationException

    807605
      Hello all,

      I am getting a ConcurrentModificationException when trying to run my code, even though I am using a ListIterator when I am iterating and removing. I wrote some sample code to show you.
      import java.awt.Color;
      import java.awt.Graphics;
      import java.util.Random;
      
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      
      public class Main extends JPanel
      {
           private Engine engine;
           
           public Main()
           {
                setBackground(Color.black);
                
                engine = new Engine();
                
                Thread t = new Thread(new Runnable()
                {
                     public void run()
                     {
                          while(true)
                          {
                               Random randNumGen = new Random();
                               if(randNumGen.nextInt(5) == 1)
                               {
                                    engine.createDots(randNumGen.nextInt(20)+1);
                               }
                               
                               repaint();
                               
                               try
                               {
                                    Thread.sleep(20);
                               }
                               catch(InterruptedException e)
                               {
                                    e.printStackTrace();
                               }
                          }
                     }
                });
                t.start();
           }
           
           public void paintComponent(Graphics g)
           {
                super.paintComponent(g);
                
                g.setColor(Color.white);
                g.drawString(engine.dots.size() + " dots", 15, 15);
                engine.draw(g);
           }
           
           public static void main(String[] args)
           {
                JFrame f = new JFrame("Test");
                f.setSize(500, 500);
                f.setLocationRelativeTo(null);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setContentPane(new Main());
                f.setVisible(true);
           }
      }
      
      /*=================================================*/
      
      import java.awt.Graphics;
      import java.util.ArrayList;
      import java.util.ListIterator;
      import java.util.Random;
      
      public class Engine
      {
           protected ArrayList<Dot> dots;
           private ListIterator<Dot> iterator;
           
           public Engine()
           {
                dots = new ArrayList<Dot>();
           }
           
           public void createDots(int num)
           {
                for(int i=0; i<num; i++)
                {
                     Random randNumGen = new Random();
                     int x = randNumGen.nextInt(500);
                     int y = randNumGen.nextInt(500);
                     Dot dot = new Dot(this, x, y);
                     dots.add(dot);
                }
           }
           
           public void actOnDots()
           {
                iterator = dots.listIterator();
                while(iterator.hasNext())
                {
                     Dot dot = iterator.next();
                     dot.act();
                }
           }
           
           public void removeDot()
           {
                if(iterator == null)
                {
                     System.err.println("Cannot remoce Dot.");
                }
                else
                {
                     iterator.remove();
                }
           }
           
           public void draw(Graphics g)
           {
                for(Dot dot : dots)
                {
                     dot.draw(g);
                }
           }
      }
      
      /*============================================*/
      
      import java.awt.Graphics;
      import java.util.Random;
      
      public class Dot
      {
           private Engine engine;
           private int xPos;
           private int yPos;
           
           public Dot(Engine e, int x, int y)
           {
                engine = e;
                xPos = x;
                yPos = y;
           }
           
           public void act()
           {
                Random randNumGen = new Random();
                if(randNumGen.nextInt(20) == 1)
                {
                     engine.removeDot();
                }
           }
           
           public void draw(Graphics g)
           {
                g.fillOval(xPos, yPos, 4, 4);
           }
      }
      Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
           at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
           at java.util.AbstractList$Itr.next(Unknown Source)
           at concurrencydemo.Engine.draw(Engine.java:54)
           at concurrencydemo.Main.paintComponent(Main.java:54)
           at javax.swing.JComponent.paint(Unknown Source)
           at javax.swing.JComponent.paintWithOffscreenBuffer(Unknown Source)
           at javax.swing.JComponent.paintDoubleBuffered(Unknown Source)
           at javax.swing.JComponent._paintImmediately(Unknown Source)
           at javax.swing.JComponent.paintImmediately(Unknown Source)
           at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
           at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(Unknown Source)
           at java.awt.event.InvocationEvent.dispatch(Unknown Source)
           at java.awt.EventQueue.dispatchEvent(Unknown Source)
           at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
           at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
           at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
           at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
           at java.awt.EventDispatchThread.run(Unknown Source)


      I occasionally get another error that completely freezes my program. Does anyone know why this happens? Thank you for your help.
        • 1. Re: ConcurrentModificationException
          791266
          This part:

          for(Dot dot : dots)

          Creates an iterator over the dots list, and the dots list is modified while the for loop is iterating.

          Kaj
          • 2. Re: ConcurrentModificationException
            807605
            I was afraid of that. :(
            Is there any way to prevent that from happening? Thanks again for the help.
            • 3. Re: ConcurrentModificationException
              807605
              A list that is accessed using a iterator should not be modified in any other way than using the same iterator.

              Otherwise it throws the Exception.
              • 4. Re: ConcurrentModificationException
                807605
                But how could I use the same iterator? If I use it in place of the for loop, won't it dusrupt the other method that is using it?
                • 5. Re: ConcurrentModificationException
                  807605
                  Does anyone know how I can solve this?
                  • 6. Re: ConcurrentModificationException
                    807605
                    This happens in almost ALL games. I have to use it a total of 3 times in mine:

                    SOLUTION:
                    for(int i = 0; i < dots.size(); i++){
                         Dot dot = dots.get(i);
                         dot.UPDATE(); //Or something 
                         if (dot.NEEDSCLEANUP())
                                  dots.remove(i--);
                    }
                    SO:
                    In your "removedot" method, DONT REMOVE TEH DOT FROM THE ARRAY: just set it's "needscleanup" boolean to TRUE. Also, make sure the line says "dots.remove( i -- ) so that after removing you go one unit back in your list

                    It's a very elegant solution :P
                    • 7. Re: ConcurrentModificationException
                      807605
                      If all else fails, use the Iterator in the old-fashioned way, only with the new generics.
                      • 8. Re: ConcurrentModificationException
                        807605
                        taifunbrowser,

                        I tried your suggestion, but I still get the exception. Here's the new code.
                        import java.awt.Color;
                        import java.awt.Graphics;
                        import java.util.Random;
                        
                        import javax.swing.JFrame;
                        import javax.swing.JPanel;
                        
                        public class Main extends JPanel
                        {
                             private Engine engine;
                             
                             public Main()
                             {
                                  setBackground(Color.black);
                                  
                                  engine = new Engine();
                                  
                                  Thread t = new Thread(new Runnable()
                                  {
                                       public void run()
                                       {
                                            while(true)
                                            {
                                                 Random randNumGen = new Random();
                                                 if(randNumGen.nextInt(5) == 1)
                                                 {
                                                      engine.createDots(randNumGen.nextInt(2000)+1);
                                                 }
                                                 
                                                 engine.actOnDots();
                                                 
                                                 repaint();
                                                 
                                                 try
                                                 {
                                                      Thread.sleep(20);
                                                 }
                                                 catch(InterruptedException e)
                                                 {
                                                      e.printStackTrace();
                                                 }
                                            }
                                       }
                                  });
                                  t.start();
                             }
                             
                             public void paintComponent(Graphics g)
                             {
                                  super.paintComponent(g);
                                  
                                  g.setColor(Color.white);
                                  g.drawString(engine.dots.size() + " dots", 15, 15);
                                  engine.draw(g);
                             }
                             
                             public static void main(String[] args)
                             {
                                  JFrame f = new JFrame("Test");
                                  f.setSize(500, 500);
                                  f.setLocationRelativeTo(null);
                                  f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                                  f.setContentPane(new Main());
                                  f.setVisible(true);
                             }
                        }
                        
                        /*=====================================================*/
                        
                        import java.awt.Graphics;
                        import java.util.ArrayList;
                        import java.util.ListIterator;
                        import java.util.Random;
                        
                        public class Engine
                        {
                             protected ArrayList<Dot> dots;
                             
                             public Engine()
                             {
                                  dots = new ArrayList<Dot>();
                             }
                             
                             public void createDots(int num)
                             {
                                  for(int i=0; i<num; i++)
                                  {
                                       Random randNumGen = new Random();
                                       int x = randNumGen.nextInt(500);
                                       int y = randNumGen.nextInt(500);
                                       Dot dot = new Dot(x, y);
                                       dots.add(dot);
                                  }
                             }
                             
                             public void actOnDots()
                             {
                                  /*
                                  ListIterator<Dot> iterator = dots.listIterator();
                                  while(iterator.hasNext())
                                  {
                                       Dot dot = iterator.next();
                                       dot.act();
                                       
                                       if(dot.shouldBeRemoved())
                                       {
                                            iterator.remove();
                                       }
                                  }*/
                                  
                                  for(int i=0; i<dots.size(); i++)
                                  {
                                       Dot dot = dots.get(i);
                                       dot.act();
                                       
                                       if(dot.shouldBeRemoved())
                                       {
                                            dots.remove(i--);
                                       }
                                  }
                             }
                             
                             public void draw(Graphics g)
                             {
                                  for(Dot dot : dots)
                                  {
                                       dot.draw(g);
                                  }
                             }
                        }
                        
                        /*=====================================================*/
                        
                        import java.awt.Graphics;
                        import java.util.Random;
                        
                        public class Dot
                        {
                             private int xPos;
                             private int yPos;
                             private boolean shouldBeRemoved = false;
                             
                             public Dot(int x, int y)
                             {
                                  xPos = x;
                                  yPos = y;
                             }
                             
                             public void act()
                             {
                                  Random randNumGen = new Random();
                                  if(randNumGen.nextInt(20) == 1)
                                  {
                                       shouldBeRemoved = true;
                                  }
                             }
                             
                             public boolean shouldBeRemoved()
                             {
                                  return shouldBeRemoved;
                             }
                             
                             public void draw(Graphics g)
                             {
                                  g.fillOval(xPos, yPos, 4, 4);
                             }
                        }
                        Both the commented and uncommented section give me errors. Thanks again for the help.