0
\$\begingroup\$

I'm programming a simple Snake in Java. I'm a complete newbie when it comes to Java and Game Developing, so please bear with me ;)

Until now, I have been using a UI thread, as well as a update-thread. The update thread just set the position, set the GameObjects, and so on.

I didn't think much of concurrency, but now I've come to a problem.

I wanted to modify the ArrayList<GameObject>, but it throws a java.util.ConcurrentModificationException.

With a little research I found out that this happens because the two threads are trying to access the variables at the same time.

But I didn't really find a way to prevent this. I thought about copying the array and swapping them out when the rendering is finished, but I would have to deep-copy them, which isn't really the best solution in my opinion. It probably eats up more CPU resources than a single-threaded game.

Are there any other ways to prevent this?

Thanks a lot for your help!

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Why do you use threads? \$\endgroup\$
    – Liosan
    Nov 23, 2012 at 12:45
  • \$\begingroup\$ @Liosan 1. So the game loop doesn't block the ui thread. 2. For practise. \$\endgroup\$
    – IluTov
    Nov 23, 2012 at 12:46
  • \$\begingroup\$ Have you tried making your Collection thread safe? One way to achieve this is using the synchronizedCollection method. \$\endgroup\$
    – Asakeron
    Nov 23, 2012 at 14:25
  • 1
    \$\begingroup\$ A thread safe Collection isn't going to make a thread safe program. Even with a synchronized collection, you will still be rendering the world in an inconsistent state. Either guard the entire update operation with a mutex, or better yet, don't use multi-threading without proper motivation. If your rendering takes so long as to lock up your UI, you have a bigger problem :) If your game updates take too long, consider splitting the work into smaller pieces and spread them out over several frames. \$\endgroup\$
    – ccxvii
    Nov 23, 2012 at 17:24

1 Answer 1

4
\$\begingroup\$

Use wait and notify to ensure that only one of your threads is modifying the object at a time. You'll need a class to hold your ArrayList:

class GameObjectManager {
    private ArrayList<GameObject> objects;
    private Boolean rendering = false;

    public GameObjectManager(){
        //Initialize objects
    }

    public synchronized void update() {
        if (rendering)
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println("InterruptedException caught");
            }

        // update objects...

        rendering = true;
        notify();
    }

    public synchronized void render() {
        if (!rendering)
            try {
                wait();
            } catch (InterruptedException e) {
                System.out.println("InterruptedException caught");
            }

        // render objects...

        rendering = false;
        notify();
    }
}

The Update thread might look something like this:

class UpdateThread implements Runnable {
    private GameObjectManager manager;

    public UpdateThread(GameObjectManager m) {
        this.manager = m;
        new Thread(this, "Update").start();
    }

    public void run() {
        while (true) {
            m.update();
        }
    }
}

The Render thread would follow suit:

class RenderThread implements Runnable {
    private GameObjectManager manager;

    public RenderThread(GameObjectManager m) {
        this.manager = m;
        new Thread(this, "Render").start();
    }

    public void run() {
        while (true) {
            m.render();
        }
    }
}

Now the main function that controls it all would do something resembling this:

public static void main(String args[]) {
    GameObjectManager manager = new GameObjectManager();
    new UpdateThread(manager);
    new RenderThread(manager);
    System.out.println("The game is running now...");
}

So here's what happens:
1. The main function creates two threads, the update and render threads.
2. Both threads try to do their task, but the GameObjectManager forces the render thread to wait() until the update thread has called notify().
3. The update thread finishes updating, notifies the render thread, and then waits.
4. The render thread finishes rendering, notifies the update thread, and then waits.

And so on.

\$\endgroup\$
4
  • \$\begingroup\$ How is this an improvement over just using a single thread? \$\endgroup\$
    – ccxvii
    Nov 23, 2012 at 16:56
  • \$\begingroup\$ Just wanted to ask this, I loose the advantages of multithreading with this... \$\endgroup\$
    – IluTov
    Nov 23, 2012 at 17:34
  • \$\begingroup\$ Updating and Rendering have to happen in sequence, there are no advantages to multithreading them at all. This is just a way to sequence them if you have threads in place already. \$\endgroup\$
    – Eric B
    Nov 23, 2012 at 18:14
  • \$\begingroup\$ @NSAddict If this removes all the advantages of multi-threading then you're not threading the right parts of your code. Eric has given you a correct answer that solves your concurrent modification issues. Deciding what code to thread is a different problem. \$\endgroup\$
    – House
    Nov 23, 2012 at 18:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .