ConcurrentModificationException

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;

publicclass Mainextends JPanel

{

private Engine engine;

public Main()

{

setBackground(Color.black);

engine =new Engine();

Thread t =new Thread(new Runnable()

{

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

}

publicvoid paintComponent(Graphics g)

{

super.paintComponent(g);

g.setColor(Color.white);

g.drawString(engine.dots.size() +" dots", 15, 15);

engine.draw(g);

}

publicstaticvoid 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;

publicclass Engine

{

protected ArrayList<Dot> dots;

private ListIterator<Dot> iterator;

public Engine()

{

dots =new ArrayList<Dot>();

}

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

}

}

publicvoid actOnDots()

{

iterator = dots.listIterator();

while(iterator.hasNext())

{

Dot dot = iterator.next();

dot.act();

}

}

publicvoid removeDot()

{

if(iterator ==null)

{

System.err.println("Cannot remoce Dot.");

}

else

{

iterator.remove();

}

}

publicvoid draw(Graphics g)

{

for(Dot dot : dots)

{

dot.draw(g);

}

}

}

/*============================================*/

import java.awt.Graphics;

import java.util.Random;

publicclass Dot

{

private Engine engine;

privateint xPos;

privateint yPos;

public Dot(Engine e,int x,int y)

{

engine = e;

xPos = x;

yPos = y;

}

publicvoid act()

{

Random randNumGen =new Random();

if(randNumGen.nextInt(20) == 1)

{

engine.removeDot();

}

}

publicvoid 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.>

[8716 byte] By [RDSmitha] at [2007-11-27 8:26:02]
# 1
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
kajbja at 2007-7-12 20:15:15 > top of Java-index,Java Essentials,Java Programming...
# 2
I was afraid of that. :(Is there any way to prevent that from happening? Thanks again for the help.
RDSmitha at 2007-7-12 20:15:16 > top of Java-index,Java Essentials,Java Programming...
# 3
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.
boneysekha at 2007-7-12 20:15:16 > top of Java-index,Java Essentials,Java Programming...
# 4
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?
RDSmitha at 2007-7-12 20:15:16 > top of Java-index,Java Essentials,Java Programming...
# 5
Does anyone know how I can solve this?
RDSmitha at 2007-7-12 20:15:16 > top of Java-index,Java Essentials,Java Programming...
# 6

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

taifunbrowsera at 2007-7-12 20:15:16 > top of Java-index,Java Essentials,Java Programming...
# 7
If all else fails, use the Iterator in the old-fashioned way, only with the new generics.
OleVVa at 2007-7-12 20:15:16 > top of Java-index,Java Essentials,Java Programming...
# 8

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.>

RDSmitha at 2007-7-12 20:15:16 > top of Java-index,Java Essentials,Java Programming...