我正在编写一个简单的Snake游戏。 所以,我有一个更新线程,执行一个无限的while循环,它会更新所有GameObject并重新绘制JPanel。
// Run thread
public void run () {
try {
while (true) {
this.update();
this.getGamePanel().sceneShouldRepaint();
Thread.sleep(this.getFps());
}
}
catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.OK_CANCEL_OPTION);
}
}
现在,问题在于,当我调用myJFrame.repaint()
时,它可能正在另一个线程中执行。当我画画时,我显然必须得到物体的位置,速度等等......
我知道异常来自paintComponent()
,因为它没有被捕获。
如您所见,while循环嵌入在try-catch中。
我该怎么办?
这是例外:
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.next(AbstractList.java:343)
at ch.ilijatovilo.Scene.GameObjects.Creatures.Snake.Snake.render(Snake.java:52)
at ch.ilijatovilo.Scene.SceneHandling.Scene.renderSceneObjects(Scene.java:57)
at ch.ilijatovilo.Scene.SceneHandling.Scene.render(Scene.java:53)
at ch.ilijatovilo.Scene.SceneHandling.GamePanel.paintComponent(GamePanel.java:53)
at ch.ilijatovilo.Scene.SceneHandling.GamePanel.paint(GamePanel.java:30)
at javax.swing.JComponent._paintImmediately(JComponent.java:5106)
at javax.swing.JComponent.paintImmediately(JComponent.java:4890)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:812)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:714)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:694)
at javax.swing.RepaintManager.access$700(RepaintManager.java:41)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1672)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:702)
at java.awt.EventQueue.access$400(EventQueue.java:82)
at java.awt.EventQueue$2.run(EventQueue.java:663)
at java.awt.EventQueue$2.run(EventQueue.java:661)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:672)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
感谢您的帮助!
HINT
如果您尝试从2个不同的线程同时访问实例,则抛出ConcurrentModificationException。这至少是我听说过的。
更多代码
// This is the render method in the Snake class at line 50.
// So 52 is the start of the for loop
public void render(Graphics g) {
// We delegate the drawing to the body parts
for (SnakeBodyPart sbp : this.getSnakeBodyParts()) {
sbp.render(g);
}
this.getSnakeHead().render(g);
}
// And here the for loop from the Scene class
protected void renderSceneObjects (Graphics g) {
for (SceneObject so : this.getSceneObjects()) {
so.render(g);
}
}
答案 0 :(得分:2)
很可能你正在改变需要在另一个线程中呈现的细节,这个库看起来不允许(我认为大多数GUI库都不允许这样做)
当您更改GUI组件或将要呈现的内容时,您需要调用SwingUtils.invokeLater(),以便任务将在GUI事件线程中执行,而不是在另一个线程中同时执行。
答案 1 :(得分:1)
CopyOnWriteArrayList是一个答案。当我有时间的时候,我会照顾另一种解决方案......
基于awt的应用程序中的另一个解决方案应该是
EventQueue.invokeLater(new Runnable() {...});
答案 2 :(得分:0)
如果你在两个线程中调整列表,你会看到像你提到的问题。如果您无法找到'Comodification',您可以依靠java.util.concurrent库。
http://docs.oracle.com/javase/tutorial/essential/concurrency/collections.html