ArrayList中的java.util.ConcurrentModificationException;尝试在绘制时添加新对象

ArrayList中的java.util.ConcurrentModificationException;尝试在绘制时添加新对象,java,arraylist,paint,Java,Arraylist,Paint,我做了一个小游戏。现在我想每隔10毫秒向播放器添加新粒子: TimerTask task2 = new TimerTask() { @Override public void run() { if(!_panel.drawing()) new HeatParticle(_panel, _player); } }; timer.schedule(task2, 10, 10);

我做了一个小游戏。现在我想每隔10毫秒向播放器添加新粒子:

    TimerTask task2 = new TimerTask() {
        @Override
        public void run() {
            if(!_panel.drawing())
            new HeatParticle(_panel, _player);
        }
    };
    timer.schedule(task2, 10, 10);
粒子将自身添加到游戏面板:

public HeatParticle(GamePanel panel, GameCircle _player) {
    _panel = panel;
    _particle = new GameCircle(_player.x() + _r.nextInt(10)  - 5  + _player.size() / 2, _player.y() + _r.nextInt(10)  - 5 + _player.size() / 2, 5, "draw", Color.RED);

    _panel.add(_particle);
    startTimer();
}
GamePanel将所有圆圈存储在ArrayList中:

private ArrayList<GameCircle> circles = new ArrayList<GameCircle>();
[...]
    public void add(GameCircle circle) {
    if (!_drawing) {
        circles.add(circle);
        circle.setIndex(circles.size() - 1);
        repaint();
    }
}
但我有一个例外:

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at jakob.GameEngine2D.GamePanel.draw(GamePanel.java:95)
at jakob.GameEngine2D.GamePanel.paint(GamePanel.java:330)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)
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._paintImmediately(JComponent.java:5158)
at javax.swing.JComponent.paintImmediately(JComponent.java:4969)
at javax.swing.RepaintManager$4.run(RepaintManager.java:831)
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)
我认为问题在于,当ArrayList在for循环中时,一个新的圆被添加到ArrayList中,我试图修复这个问题(布尔图),但它不起作用。你能帮我吗?
-Jakob

尝试一个并发列表,例如

当您使用
迭代器
到此数据结构时,不得更改基础数据结构,否则您将得到此
异常
(一个
foreach
循环在后台使用
迭代器)。一个简单的解决方法是使用一个普通的
for
循环,但是由于并发性问题,这可能会跳过一些元素。我现在正在使用它,它可以工作。谢谢解决了问题,一切正常。谢谢所有粒子现在都很高兴:@Jakob注意到这个类效率很低,因为它在每次写入时都会创建列表的新副本。与使用此“快速”解决方案相比,正确同步操作会更好。但是如何同步呢?我的解决方案(布尔图形)不起作用。编辑:当前的解决方案占用了太多的CPU电源(i7-4790k@4,7GHz):为什么CPU电源会随着时间的推移而增加?圆圈.size()保持在40到55之间。
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at jakob.GameEngine2D.GamePanel.draw(GamePanel.java:95)
at jakob.GameEngine2D.GamePanel.paint(GamePanel.java:330)
at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)
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._paintImmediately(JComponent.java:5158)
at javax.swing.JComponent.paintImmediately(JComponent.java:4969)
at javax.swing.RepaintManager$4.run(RepaintManager.java:831)
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)