ConcurrentModificationException over list - PullRequest
0 голосов
/ 07 июня 2011

Я пытаюсь перебрать список объектов. Я получаю ошибку ConcurrentModificationException. Однако я не изменяю / удаляю объекты. Также синхронизируется метод game.getRooms (). Что я делаю не так?

Iterator<Room> it = game.getRooms().iterator();
     while (it.hasNext()) {
        Room room = it.next();
        synchronized (room) { 
           Image tile;
           if (room.getTile() == Tiles.WALL) {
              tile = TileGraphics.wall;
           } else if (room.getTile() == Tiles.EXIT) {
              tile = TileGraphics.exit;
           } else {
              tile = TileGraphics.floor;
           }
           tile.setAlpha(room.getLight());
           tile.draw(room.getX() * tile.getWidth(), room.getY() * tile.getHeight());
        }
     }

StackTrace:

java.util.ConcurrentModificationException at java.util.AbstractList $ Itr.checkForComodification (неизвестный источник) at java.util.AbstractList $ Itr.next (неизвестный источник) на game.screens.GameScreen.render (GameScreen.java:62) в org.newdawn.slick.state.StateBasedGame.render (StateBasedGame.java:199) в org.newdawn.slick.GameContainer.updateAndRender (GameContainer.java:681) в org.newdawn.slick.AppGameContainer.gameLoop (AppGameContainer.java:408) на org.newdawn.slick.AppGameContainer.start (AppGameContainer.java:318) на game.Main.main (Main.java:23) Вт июнь 07 22:05:03 EEST 2011 ОШИБКА: Ошибка Game.render () - проверьте код игры. org.newdawn.slick.SlickException: ошибка Game.render () - проверьте код игры. в org.newdawn.slick.GameContainer.updateAndRender (GameContainer.java:684) в org.newdawn.slick.AppGameContainer.gameLoop (AppGameContainer.java:408) на org.newdawn.slick.AppGameContainer.start (AppGameContainer.java:318) at game.Main.main (Main.java:23)

Строка 62 Room room = it.next();

Ответы [ 4 ]

4 голосов
/ 07 июня 2011

Конечно, есть код, который изменяет этот список где-то еще в другом потоке. Поэтому можно создать копию списка и повторить ее (с помощью foreach):

List<Room> copy = new ArrayList<Room>(game.getRooms());
for (Room room : copy) {..}
3 голосов
/ 07 июня 2011

Если этот список используется в многопоточном приложении, любой поток может получать доступ к списку и изменять / перебирать список поддержки с помощью итератора.

Ваш список создается с помощью синхронизированной оболочки? (Collections.synchronizedList (например, новый ArrayList ()).

Синхронизация объявления списка недостаточна, и не просто синхронизация вызова метода. Каждое место, в котором повторяется список, нуждается в синхронизированном блоке, синхронизированном со списком.

Чтение http://download.oracle.com/javase/6/docs/api/java/util/Collections.html#synchronizedList(java.util.List)

0 голосов
/ 07 июня 2011

Slick управляет всеми потоками для логики, рендеринга и т. Д., Так что, вероятно, это другой поток внутри Slick, который делает это - возможно, где-то в логическом потоке (то есть, в методе update () для вашей игры). 1001 *

Если вы не вносите никаких изменений в приведенный выше код, зачем синхронизировать? Вы пробовали это без синхронизации, чтобы видеть, работает ли это?

Учитывая, что Slick должен обрабатывать для вас рендеринг и логические потоки / циклы, я думаю, вам повезет больше, если вы немного ослабли и позволили Slick сделать свое дело. Может быть, вам здесь вообще не нужна синхронизация.

0 голосов
/ 07 июня 2011

Тот факт, что getRooms синхронизирован, никак не влияет на код.Это влияет только на вызов getRooms ().

Лучшим подходом будет попытка synchronized (game) {game.getRooms ();.. iterate}

Или даже синхронизированы (game.getRooms ()) {... iterate}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...