🔒 Locked
[java] ConcurrentModificationException
Advertisement
Original Post
Hey guys. I'm working on an old-fashioned up-and-down-scrolling space shooter in Java. Today I implemented a scrolling starfield to give the appearance that the player's ship is moving. What I'm doing is randomly generating one star every few frames. Then I add that star to a linked list of stars so that I can keep track of their positions in order to display them. This works and looks very well. However, for obvious reasons, if left running, the program bogs down because the linkedlist becomes enormous and the application must iterate through this gigantic list every frame. So of course I decided to remove stars from this linkedlist once they are no longer in view. But it seems like whenever I try to remove them from the list, I get a runtime error: the concurrentModificationException. I know vaguely what that means: I think it means that I'm not supposed to make changes to the list while I'm still iterating over it. But how am I supposed to know which stars to delete if I can't iterate over the list?!
Im not 100 % sure, But i think it means you have iterators elesewhere belonging to this list. I believe that if you only have 1 iterator to the list, then the exception will not be thrown.
Yes, looking at the documentation that seems to be the case, excpet that if you editing the list directly ( not using the iterator ) can also cause the exception.
What is your code like?
Yes, looking at the documentation that seems to be the case, excpet that if you editing the list directly ( not using the iterator ) can also cause the exception.
What is your code like?
import java.awt.*;import javax.swing.*;import java.awt.image.*;import java.awt.event.*;import java.util.*;public class Ascendancy implements KeyListener{ private boolean gameRunning = true; private int x = 100; private int y = 100; private int vx = 0; private int vy = 0; private int speed = 4; private int size = 50; private boolean up = false; private boolean down = false; private boolean left = false; private boolean right = false; private boolean deccel = false; //private boolean accel = false; private int dc = 1; private int rate = 20; private LinkedList<Star> stars = new LinkedList<Star>(); public Ascendancy() { JFrame f = new JFrame("Ascendancy"); f.setSize(800, 600); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.addKeyListener(this); f.setVisible(true); f.createBufferStrategy(2); //start game game(f.getBufferStrategy()); } public void game(BufferStrategy s) { //main game loop while (gameRunning) { Graphics g = s.getDrawGraphics(); updateWorld(); renderWorld(g); s.show(); sleep(); if (deccel) dc++; } }public void renderWorld(Graphics g) { g.setColor(Color.BLACK); g.fillRect(0, 0, 800, 600); drawSF(g); g.setColor(Color.GRAY); drawFighter(g, x, y); } public void updateWorld() { updateSF(); double d = Math.random(); if (d > 0.5) createStar((int)Math.round(Math.random()*800)); x += vx; y += vy; if (deccel) { if (dc % rate == 0 && vx != 0 && vy != 0) { if (vx > 0) vx--; else vx++; if (vy > 0) vy--; else vy++; if (vx == 0 && vy == 0) dc = 0; } } } public void sleep() { try { Thread.sleep(10); } catch (Exception e) { } } public static void main(String[] args) { new Ascendancy(); }public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_ESCAPE: System.exit(0); break; case KeyEvent.VK_UP: up = true; dc = 1; deccel = false; vy = -1 * speed; break; case KeyEvent.VK_DOWN: down = true; dc = 1; deccel = false; vy = speed; break; case KeyEvent.VK_LEFT: left = true; dc = 1; deccel = false; vx = -1 * speed; break; case KeyEvent.VK_RIGHT: right = true; dc = 1; deccel = false; vx = speed; break; } }public void keyReleased(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_UP: up = false; deccel = true; break; case KeyEvent.VK_DOWN: down = false; deccel = true; break; case KeyEvent.VK_LEFT: left = false; deccel = true; break; case KeyEvent.VK_RIGHT: right = false; deccel = true; break; } } public void keyTyped(KeyEvent e) { } public void updateSF() { for (Star s : stars) { s.y = s.y+5; if (s.y > 600) stars.remove(s); } } public void purgeSF() { } public void createStar(int x) { stars.add(new Star(x, 0)); }public void drawSF(Graphics g) { g.setColor(Color.WHITE); for (Star s : stars) { g.drawLine(s.x, s.y, s.x, s.y+10); } } public void drawFighter(Graphics g, int x, int y) { g.drawLine(x, y, x+5, y+20); g.drawLine(x, y, x-5, y+20); g.drawLine(x+5, y+20, x+5, y+40); g.drawLine(x-5, y+20, x-5, y+40); g.drawLine(x+5, y+40, x+25, y+55); g.drawLine(x-5, y+40, x-25, y+55); g.drawLine(x-25, y+55, x-5, y+55); g.drawLine(x+25, y+55, x+5, y+55); g.drawLine(x+5, y+55, x+5, y+60); g.drawLine(x-5, y+55, x-5, y+60); g.drawLine(x+5, y+60, x+10, y+65); g.drawLine(x-5, y+60, x-10, y+65); g.drawLine(x-10, y+65, x-5, y+65); g.drawLine(x+10, y+65, x+5, y+65); g.drawLine(x+5, y+65, x+4, y+68); g.drawLine(x-5, y+65, x-4, y+68); g.drawLine(x-4, y+68, x+4, y+68); g.setColor(Color.ORANGE); g.drawLine(x-4, y+68, x, y+75); g.drawLine(x+4, y+68, x, y+75); }}Sorry for the lack of documentation right now. The methods of interest are createStar(), drawSF(), updateSF(), as those are the ones that deal with the linkedlist (called stars).
Hmm haven't really used Java 1.5, but it seems this contains a hidden iterator, which gets worried wehen you directly edit the list (stars.remove )
Try writing it out longhand and see if the error still occurs:
Mind you I haven't used java in a bit, and haven't more than read up on 1.5, so it might not even compile, let alone fix your problem.
Hope it helps either way. Good Luck!
for (Star s : stars){ s.y = s.y+5; if (s.y > 600) stars.remove(s);}Try writing it out longhand and see if the error still occurs:
for ( ListIterator<Star> it = stars.getListIterator() ; it.hasNext() ; ){ Star s = it.next(); s.y = s.y+5; if (s.y > 600) it.remove(); }Mind you I haven't used java in a bit, and haven't more than read up on 1.5, so it might not even compile, let alone fix your problem.
Hope it helps either way. Good Luck!
Ah, yes, the good old ConcurrentModificationException (try saying that -- or typing it! -- three times fast [smile]). I've encountered this problem before as well. There is actually a simple solution that still lets you use the new for-each construct in 1.5. All you need to do is implement another list for stars that need to be removed. For each frame, every star that needs to be removed is put in that list. Once the program is done running through the main list of stars, you simply call
This approach is easy to use and completely takes away your ConcurrentModificationException worries. It's worked for me with e.g. removing missiles once they go beyond the bounds of the screen (or map).
Hope this helps. [smile]
stars.removeAll(removedStars);This approach is easy to use and completely takes away your ConcurrentModificationException worries. It's worked for me with e.g. removing missiles once they go beyond the bounds of the screen (or map).
Hope this helps. [smile]
Hmph.
I have another problem. Maybe you guys can help. For some reason, the game gets slower and slower until I'm only getting about 3 or 4 FPS (after about an hour).
I've been monitoring the memory usage and it's remained relatively static. I just don't know what's causing this slowdown. It starts off smooth as a baby's bottom! The only real thing I changed was this:
I have another problem. Maybe you guys can help. For some reason, the game gets slower and slower until I'm only getting about 3 or 4 FPS (after about an hour).
I've been monitoring the memory usage and it's remained relatively static. I just don't know what's causing this slowdown. It starts off smooth as a baby's bottom! The only real thing I changed was this:
public void updateSF() { for (Star s : stars) { s.updatePos(); if (s.gone()) starsAwaitingRemoval.add(s); } stars.removeAll(starsAwaitingRemoval); }
It'd be nice to see a working prototype Kevinator.
I've always been interested in seeing some of the games that people post questions for on here. I'd like to think that a lot of progress is being made rather than just a crap load of question upon question without anything to show for all of it.
Also, I'm curious how well the scrolling starfield worked out! [grin]
I've always been interested in seeing some of the games that people post questions for on here. I'd like to think that a lot of progress is being made rather than just a crap load of question upon question without anything to show for all of it.
Also, I'm curious how well the scrolling starfield worked out! [grin]
I have to ask why I you making this so complicated?
I would of done it like this, could be placed in its own class.
final int numStars = 30;
double starX[] = new double [numStars];
double starX[] = new double [numStars];
All you need to do is when a star passes of the side of you place it on the other side with a random y and like wise for sides the leave the top / bottom of the screen.
link lists for something as simple as this is overkill, kind of like shooting an ant with a cannon and is much more efficient CPU wise.
And you could even add color as well!
Just some ideas.... :-)
I would of done it like this, could be placed in its own class.
final int numStars = 30;
double starX[] = new double [numStars];
double starX[] = new double [numStars];
All you need to do is when a star passes of the side of you place it on the other side with a random y and like wise for sides the leave the top / bottom of the screen.
link lists for something as simple as this is overkill, kind of like shooting an ant with a cannon and is much more efficient CPU wise.
And you could even add color as well!
Just some ideas.... :-)
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement