2014-11-02 55 views
-1

出於某種原因,我看了很多帖子,但我不知道如何解決這個問題。 在我的遊戲的更新方法中,我有一個更新所有現有GameObjects的for循環。怪異的併發修改異常

private static void update() { 
    for (GameObject g : GameObjectManager.getGameObjects()) { 
     g.update(); 
    } 
    canvas.repaint(); 
} 

它說在for循環行有一個ConcurrentModificationException錯誤。 我曾嘗試過,像有人說的那樣,獲取遊戲對象列表的迭代器,然後使用它,但它仍然不起作用。 儘管它表示錯誤行位於for循環,但當我刪除g.update時,沒有更多錯誤。 編輯:我發現了錯誤。它將一個遊戲對象添加到GameObjectManager.registerGameObject()中的列表中。 使用了更新的唯一其他類是這樣的:

public class PaintCanvas extends JPanel { 
    private static final long serialVersionUID = 6718161148154673832L; 

    { 
     this.setDoubleBuffered(true); 
     this.setVisible(true); 
    } 

    @Override 
    public void paint(Graphics g) { 
     g.setColor(Color.RED); 
     for (GameObject go : GameObjectManager.getGameObjects()) { 
      g.fillRect(go.getPosition().getX(), go.getPosition().getY(), 30, 30); 
     } 
    } 
} 

唯一的更新方法是這樣的:

@Override 
public void update() { 
    Random r = new Random(); 
    int spawn = r.nextInt(100); 
    // 5% Chance to spawn 
    if (spawn <= 5) { 
     Spawner s = new Spawner(); 
     s.setPosition(new Point(4, 50)); 
    } 
} 
+0

問題不是GameObjects被修改,而是列表本身,而迭代它: GameObjectManager.getGameObjects()<----這個調用返回的列表。也許g.update()從這個列表中刪除或添加其他GameObjects? – Chrisport 2014-11-02 19:59:03

回答

2

在迭代它不能修改的列表。其中一個遊戲對象的更新方法必須是添加或刪除項目。

可以遍歷一個副本:

for (GameObject g : new ArrayList(GameObjectManager.getGameObjects())) { 
    g.update(); 
} 

或者使用一個正常的循環,這裏的對象可以安全地添加,但不會被刪除:

List<GameObject> objects = GameObjectManager.getGameObjects(); 
int size = objects.size(); 
for(int i = 0; i < size; i++) { 
    GameObject g = objects.get(i); 
    g.update(); 
} 

或修復GameObjectManager.registerGameObject()添加到臨時列表,而不是主列表,並將它們移動到現有代碼之前的主列表中。清除同樣可以完成。

GameObjectManager.promoteNewGameObjects(); //promote objects added in the last frame 
for (GameObject g : GameObjectManager.getGameObjects()) { 
    g.update(); //as before 
} 
+0

對不起,我現在添加了更新方法。 – MCMastery 2014-11-02 20:26:22

+0

爲您增加了一些選項。 – weston 2014-11-02 22:03:11

+0

謝謝weston – MCMastery 2014-11-03 22:53:17

2

在這種情況下,當某些事情正在嘗試修改某個數組而正在使用它時(例如迭代它)等等,這個異常將被拋出。就像在地圖上生成一個新怪物並添加到怪物列表中,而gameloop當前正在迭代所述列表。在你的GameObjectManager類中,你用什麼來存儲GameObject的?如果這是一個正常的列表,你應該考慮將其更改爲CopyOnWriteArrayList或任何其他線程安全列表,它應該解決這個問題。

+0

我發現這個錯誤實際上是在向列表中添加一個遊戲對象時。 (只是一個簡單的List.add)。如何將該行更改爲線程安全? – MCMastery 2014-11-02 20:28:34

+0

您可以使用線程安全列表(如CopyOnWriteArrayList)或自己同步這些錯誤引發塊。第二種方法更爲複雜,如果您想手動執行,請閱讀關於同步和併發性的內容。同步基本上給一個對象一個「鍵」,只要它對它有效,而其他方法不能訪問該對象,直到這個鍵再次可用。 – FruitAddict 2014-11-02 20:34:38