You are modifying your list structurally in update thread while, at the same time, the render thread has created an Iterator and is having fun iterating your objects. You're getting ConcurrentModificationException
as a punishment for not handling synchronization issues.
Try searching for any example with synchronized block/method and wait()/notify().
UPD: Ok, here is a simple modification of your code, which does not throw an exception. This is not a good example of List synchronization, you do not gain much performance (update and render operations are still in different threads, but performed sequentially), and there are few things to consider - if any other thread tries to modify your List, you will still get a concurrent exception.
In your launcher class define two threads:
private Thread t1, t2;
Code that lauches threads (e.g., inside public static void main(..)
):
final List<GameObject> list = initList();//some initialization
t1 = new Thread(new Runnable() {
@Override
public void run() {
myMultipurposeMethod(list);
}
});
t2 = new Thread(new Runnable() {
@Override
public void run() {
myMultipurposeMethod(list);
}
});
t1.start();
t2.start();
Now a simplified version of your GameObject class. Pay attention to synchronized blocks:
class GameObject {
private int id;
private static int count = 0;
private boolean shouldDelete = false;
private Object monitor = new Object();//will be used to lock critical section
public GameObject() {
id = ++count;
}
public void update(Thread thread) {
synchronized (monitor) {
shouldDelete = Math.random() < 0.5;//just a simple randomization
System.out.println(thread.getName() + " updates GameObject. should be removed =" + shouldBeRemoved());
}
}
public boolean shouldBeRemoved() {
synchronized (monitor) {
return shouldDelete;
}
}
public void render(Thread thread) {
System.out.println(thread.getName() + " renders GameObject " + id);
}
}
And finally, your multipurpose method:
public void myMultipurposeMethod(List<GameObject> ls) {
synchronized (ls) {
if (Thread.currentThread().equals(t1)) {
while (true) {
for (Iterator<GameObject> i = ls.iterator(); i.hasNext(); ) {
i.next().render(Thread.currentThread());
ls.notify();
}
try {
ls.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else if (Thread.currentThread().equals(t2)) {
while (true) {
for (Iterator<GameObject> i = ls.iterator(); i.hasNext(); ) {
GameObject o = i.next();
o.update(Thread.currentThread());
if (o.shouldBeRemoved()) {
i.remove();
System.out.println("game object with id=" + o.id + " marked as garbage and was removed");
}
}
ls.notify();
try {
ls.wait();
} catch (InterruptedException e) {
e.printStackTract();
}
}
}
}
}
That will give you an illusion of parallel execution and prevent your Exception from happening, if you follow the requirements given in the preamble. However, in order to achieve a real performance gains, you would be better off following @isnot2bad advices given in the comments to OP.