编辑:问题解决了!
感谢大家的帮助。我知道我需要同步一套,只是无法解决哪一个问题。相当令人尴尬的是,我已经同步了正确的一个,但没有将同步集分配给变量。哦,我们生活和学习。
我对Java比较新,这是我的第一个个人项目。我试图建立一个简单的2d平台游戏,并且有一个我无法弄清楚的ConcurrentModificationException弹出窗口。我已经搜索了一段时间,但找不到任何像我一样的问题的人。问题出现在以下方法中:
public Set<Platform> change(Set<Platform> platforms)
{
Set<Platform> viewSet = new HashSet<Platform>();
Point abPos = ball.getAbPos();
int viewWidth, viewHeight, viewXPos, viewYPos;
for (Platform p : platforms) {
if (null != p.getType()) {
switch (p.getType()) {
case PLATFORM:{
viewWidth = p.getWidth() * xRatio;
viewHeight = p.getHeight() * yRatio;
viewXPos = (p.getX() - ball.getX()) * xRatio + abPos.x;
viewYPos = (p.getY() - ball.getY()) * yRatio + abPos.y;
viewSet.add(new Platform(viewXPos, viewYPos, viewWidth, viewHeight, p.getType()));
break;
}
case WALL:{
viewWidth = p.getWidth() * xRatio;
viewHeight = p.getHeight() * yRatio;
viewXPos = (p.getX() - ball.getX()) * xRatio + abPos.x;
viewYPos = (p.getY() - ball.getY()) * yRatio + abPos.y;
viewSet.add(new Platform(viewXPos, viewYPos, viewWidth, viewHeight, p.getType()));
break;
}
case DROP:
break;
default:
break;
}
} else {
}
}
return viewSet;
}
该方法在JPanel的paintComponent()方法中调用,来自我创建的Camera对象,其作用是获取方法传递给它的对象列表,并调整它们以进行绘制。这在每次游戏迭代中发生一次。传递给方法的对象列表是在每次迭代时从玩家的设定距离收集的,并且返回的已调整大小的对象列表由paintComponent()方法绘制。
问题是,当我启动for循环迭代传递给方法的对象列表时,change()方法通常会抛出ConcurrentModificationException,尽管不是每次迭代。我真的无法解决为什么因为抛出异常的列表没有以任何方式修改。任何帮助都会非常感激,因为我开始拔头发。我尝试过同步各种方法或集合,但这似乎没有任何区别,除了有时使代码滞后。
我得到的错误如下:
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
at java.util.HashMap$KeyIterator.next(HashMap.java:1453)
at mygame_2.Camera.change(Camera.java:39)
at mygame_2.Game2Window$DrawingPanel.paintComponent(Game2Window.java:237)
at javax.swing.JComponent.paint(JComponent.java:1056)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paint(JComponent.java:1065)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at javax.swing.JComponent.paintChildren(JComponent.java:889)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5217)
at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
at javax.swing.JComponent.paint(JComponent.java:1042)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
at java.awt.Container.paint(Container.java:1975)
at java.awt.Window.paint(Window.java:3912)
at javax.swing.RepaintManager$4.run(RepaintManager.java:842)
at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
如果代码或此问题混乱,请道歉。
答案 0 :(得分:0)
变量viewSet
是本地的,因此不会抛出异常,因此消除不可能,唯一可以引发此异常的集合就是您传递的异常。
你传入的Set
必须来自某个地方,必须要填补它。由于paintComponent
发生在Swing渲染线程上,所以冲突可能是您正在读取Swing线程上的Set
,同时在另一个线程上修改它。
如果您在synchronized
块内对此集进行了修改,并且在Set
块中遍历了synchronized
,则问题应该会消失:
synchronized (set) {
// read/write here
}
在两种情况下,变量set
都应该是相同的。
答案 1 :(得分:0)
我在使用for-each循环时只得到了这个错误。尝试切换for-each循环以获得传统的for循环。它应该摆脱错误。