0

I am not using threads, but I keep getting an error saying:

"Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException"

Here is my code:

@Override
public void paint(Graphics g) {
    for(Rectangles emp: shapes.list) {
        //Loop through all rectangle objects
        for(int[] temp: emp.arr) {
            //Loop through each objects array
            g.drawRect(temp[0], temp[1], 20, 20);
    g.drawRect(20, 20, 20, 20);
        }
    }
}

There is also a method from a different class that executes very near the paint method, over and over again, which may be causing the problem.

public class Shapes {
LinkedList<Rectangles> list  = new LinkedList<Rectangles>();
Random rand = new Random();
void newshape() {
    int shape = rand.nextInt(7);
    switch(shape) {
        case 0:
            list.add(makeSquare());
            break;
        case 1:
            list.add(makeLine());
            break;
        case 2:
            list.add(makeTShape());
            break;
        case 3:
            list.add(makeLShape());
            break;
        case 4:
            list.add(makeJShape());
            break;
        case 5:
            list.add(makeZShape());
            break;
        case 6:
            list.add(makeSShape());
            break;
        }
    }

I am using the Notch game loop, with the tick() method calling the newshape() method if it has been one second since the last time a new shape was made. The paint method is then called.

public void run(Game game) {
    while(true) {
        lastshapemake = System.nanoTime();
        long lastTime = System.nanoTime();
        double Target_FPS = 60.0;
        double ns = 1000000000 / Target_FPS;
        double delta = 0;
        while(running) { 
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while(delta >= 1) {
                tick();
                delta--;

            }
            if(running) {
                game.repaint();
            }
        }   
    }
}
  • 5
    Do you have more information about the error like the callstack or which line it is occurring on? – dolan Sep 08 '18 at 23:05
  • @dolan i'm new to java what should i do to find out this information? I'm using eclipse – OnEdge Gaming Sep 08 '18 at 23:15
  • I am not familiar with eclipse but immediately below any exception there should be a stack trace of where the exception occurred. Good luck! – dolan Sep 08 '18 at 23:16
  • 1
    I can't see how that could would generate a `ConcurrentModificationException`, I think there's more to this problem then you are showing us. Let's also start with overriding `paint` is a bad idea, not calling it's super implementation is a bad idea and modifying the state of the model from within a paint method is a bad idea. A [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve) would go along way to helping us help you – MadProgrammer Sep 08 '18 at 23:19
  • Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException at java.base/java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:970) at java.base/java.util.LinkedList$ListItr.next(LinkedList.java:892) at game.Game.paint(Game.java:60) -Thats the start of the error message but it goes on like that for too long to post it in a comment – OnEdge Gaming Sep 08 '18 at 23:20
  • Basically my program decides a random set of 4 x and y values for rectangles, stores them in an array, and then repaint() is called to display them. – OnEdge Gaming Sep 08 '18 at 23:23
  • I have a game loop and three different classes, should i post all the code? – OnEdge Gaming Sep 08 '18 at 23:23

2 Answers2

2

The problem is that you are using multiple threads even if you didn't realize it:

  1. Your main thread
  2. The Swing UI thread

Swing (and most GUI frameworks out there) are single-threaded in the sense that only one thread should manipulate the GUI and any data on which the GUI depends.

See: Why is Swing threading model considered wrong and how should it be?

The repaint method doesn't paint immediately; it puts an event on the event queue and when that event is picked up by the Swing thread, then it executes your repainting code.

During your tick method, which you haven't posted, you are updating the same list that you are iterating over in your paint method, and because the paint method sometimes runs at exactly the same time as your tick method, that causes the ConcurrentModificationExceptions.

There are a couple of ways around that.

  1. You could use double buffering, let your main thread update the non-visible buffer, and let the repaint method display the buffer when it is ready.
  2. You could run everything on the Swing thread, using EventQueue.invokeLater or javax.swing.Timer (you could schedule your tick method that way)
  3. You could copy the list in your paint method before iterating over it. However, since you are using multiple threads, that can cause data races unless you take special precautions. You could use a CopyOnWriteArrayList instead of an ordinary ArrayList, or use the Collections.synchronizedList to turn an ordinary list into one the safely publishes changes in one thread to the other thread.
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
1

ConcurrentModificationException has no relation to threads.

All it means is: We're at point 'Z' in the following timeline:

  • At point X, you grab an iterator off of a collection.
  • At point Y (after X), the collection is modified by somebody (can be in another thread, or in your own thread, it doesn't matter where it happens).
  • At point Z (after Y), you call any operation on the iterator obtained in X.

Note that you create an iterator upon entering a for (Type elem : someCollection) block, and you call the next operation on that iterator anytime that for loop loops.

From your code it's not possible to tell where the modification happens (you aren't doing it; something as simple as collection.remove(x) inside a for loop can cause a ConcurrentModificationException, but you're not doing that in the snippet you pasted).

Note that with swing you can have multiple threads even if you don't think you do. So, if that snippet is truly all you have there, another thread is involved and they are modifying shapes or one of the items in shapes.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • Thanks, i have updated the question to explain my code better, do you know what I need to do to fix the problem? There is definitely no other thread involved btw. – OnEdge Gaming Sep 08 '18 at 23:37
  • @OnEdgeGaming - There definitely is ... but you haven't realized it yet. – Stephen C Sep 09 '18 at 01:48