java.util.ConcurrentModificationException в игровом цикле Android
Я использую холст, перемещая объекты на экране, когда объект попадает на левую сторону холста (x=0), создается другой объект того же типа и начинает двигаться на экране.
Все работает отлично, несколько объектов создаются и начинают двигаться по экрану.
В определенный момент я получаю исключение одновременной модификации в моем методе run, где находится игровой цикл, где gameObjs является 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);
}
}
Я пытался использовать итератор, но все равно получаю ту же ошибку.
Я действительно ценю твою помощь. Заранее спасибо!
1 ответ
Collections.synchronizedList(...) не будет работать, если что-то подобное происходит... (выдает исключение 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();
}
}
Попробуйте найти другие места в вашем коде, где этот список изменяется. Должен быть другой поток, управляющий коллекцией, пока вы выполняете ее.
Вы можете взять копию списка, прежде чем перебирать его.
Например, в приведенном выше коде попробуйте...
for(String thing : new ArrayList<>(things)) {
...вместо...
for(String thing : Collections.synchronizedList(things)) {
... и вы больше не получите исключение (но это все равно не будет "правильным", если вы запустите его, вы увидите множество распечатанных нулей...)
Еще лучше сохранить цикл чтения как...
for(String thing : things) {
... но измените тип списка...
List<String> things = new CopyOnWriteArrayList<>();