2

I am using a canvas, moving objects on the screen, when an object hit the left side of the canvas (x=0), another object of the same type gets instantiated, and start moving on the screen.

Everything works fine, a few objects gets created and start moving around the screen.

At a certain point, I receive a concurrent modification exception in my run method where the game loop is, where gameObjs is an ArrayList:

@Override
public void run() {

    while(isRunning){
        if(!myHolder.getSurface().isValid())
            continue;
        Canvas canvas = myHolder.lockCanvas();
        canvas.drawRect(0,0,canvas.getWidth(), canvas.getHeight(), pWhite);


        for(MyGameObject gameObj : gameObjs){
            gameObj.move(canvas);
        }

        myHolder.unlockCanvasAndPost(canvas);
    }

}

I've tried to use an Iterator, but still getting the same error.

I really appreciate your help. Thank you in advance!

5
  • 1
    What type of object is gameObjs? (i.e. an ArrayList?) Is another thread running that is adding / removing items in this collection? If this is happening and it is allowed, you could use a CopyOnWriteArrayList or some other collection that allows concurrent modification... Commented Nov 17, 2016 at 17:32
  • Sorry, I've not specified gameObjs is an ArrayList Commented Nov 17, 2016 at 17:34
  • "I've not specified gameObjs is an ArrayList" But in the question you specifically say: "...where gameObjs is an ArrayList". Commented Nov 17, 2016 at 17:40
  • I've modified later, after the guys asked Commented Nov 17, 2016 at 17:41
  • Can you post the exact snipped of the code where you are receiving the exception? This exception can happen for example when you are trying to remove an item from the list while iterating over it. Commented Nov 17, 2016 at 17:41

1 Answer 1

1

Collections.synchronizedList(...) won't work if something like this is happening... (throws a ConcurrentModificationException...)

public class ConcurrentTest {

    public static void main(String[] args) {
        List<String> things = new ArrayList<>();

        Runnable modifyThread = () -> {
            while(true) {
                for(int k = 0; k < 1000; k++) {
                    things.add(String.valueOf(k));
                }

                while(!things.isEmpty()) {
                    things.remove(0);
                }
            }
        };

        Runnable readThread = () -> {
            while(true) {
                for(String thing : Collections.synchronizedList(things)) {
                    System.out.println(thing);
                }
            }
        };

        new Thread(modifyThread).start();
        new Thread(readThread).start();
    }
}

Try and find other places in your code where this list is being modified. There must be another thread manipulating the collection while you are iterating through it.

You could take a copy of the list before iterating over it.

For example, in the code above, try...

for(String thing : new ArrayList<>(things)) {

...instead of...

for(String thing : Collections.synchronizedList(things)) {

...and you will no longer get an exception (but this still won't be "correct", if you run it, you will see loads of nulls being printed out...)

Even better, keep the read loop as...

for(String thing : things) {

...but change the type of list...

List<String> things = new CopyOnWriteArrayList<>();
1
  • Thank @BretC I am using the same loop, I've just modified the List to CopyOnWriteArrayList, works perfectly! Commented Nov 17, 2016 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.