我正在努力在我运行的游戏循环中解决这个问题。
我在Update()过程中有以下一个线程:
ListIterator<ExplosionClass> litr = Explosions.listIterator();
while(litr.hasNext()){
ExplosionClass element = (ExplosionClass) litr.next();
if (element.FinishedExplosion) {
litr.remove();
}
}
我在litr.next()上间歇性地得到一个ConcurrentModificationException;
我正在通过另一个过程不时地将新项目添加到Explosions列表中。
我在第二个线程上的游戏循环如下:
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
sleepTime = 0;
// render state to the screen
// draws the canvas on the panel
while (running) {
//while (!paused && running) {
canvas = null;
synchronized (this) {
while (isPaused) {
try {
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.gamePanel.render(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
this.wait();
} catch (InterruptedException e) {
}
}
}
// try locking the canvas for exclusive pixel editing
// in the surface
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
beginTime = System.currentTimeMillis();
framesSkipped = 0; // resetting the frames skipped
// update game state
if (!isPaused && running) this.gamePanel.update();
// render state to the screen
// draws the canvas on the panel
if (!isPaused) this.gamePanel.render(canvas);
// calculate how long did the cycle take
timeDiff = System.currentTimeMillis() - beginTime;
// calculate sleep time
sleepTime = (int)(FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
// if sleepTime > 0 we're OK
try {
// send the thread to sleep for a short period
// very useful for battery saving
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// we need to catch up
// update without rendering
if (!isPaused && running) this.gamePanel.update();
// add frame period to check if in next frame
sleepTime += FRAME_PERIOD;
framesSkipped++;
}
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
try {
Thread.sleep(FRAME_PERIOD);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//}
}
事实上,你不能这样做:当你使用迭代器、同步或其他锁定机制对列表进行迭代时,你必须确保其他线程没有更改列表。
问题是,如果两个迭代器同时修改集合的内部结构,会导致ConcurrentModification异常。要处理此问题,请使用同步集合(CopyOnWriteArrayList)
在列表上调用迭代器时,迭代器工作时无法对其进行修改。