2015-12-21 61 views
0

我已經做了一個小遊戲。現在我想新的粒子添加到播放器每隔10ms:ArrayList中的java.util.ConcurrentModificationException;試圖在繪畫時添加新對象

TimerTask task2 = new TimerTask() { 
     @Override 
     public void run() { 
      if(!_panel.drawing()) 
      new HeatParticle(_panel, _player); 
     } 
    }; 
    timer.schedule(task2, 10, 10); 

的粒子將自身添加到的GamePanel:

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(); 
    } 
} 

要繪製所有這些,它用於:

private void draw() { 
_drawing = true; 
[...] 
for (GameCircle circle : circles) { 
     if (circle != null) 
      if (circle.drawOrFill() != null) 
       if (circle.drawOrFill().equals("fill") && circle.draw()) { 
        _canvas.setColor(circle.color()); 
        _canvas.fillOval(circle.x(), circle.y(), circle.size(), circle.size()); 
       } else if (circle.drawOrFill().equals("draw") && circle.draw()) { 
        _canvas.setColor(circle.color()); 
        _canvas.drawOval(circle.x(), circle.y(), circle.size(), circle.size()); 
       } 

    } 
_drawing = false; 
} 

但我得到一個異常:

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循環和從來就試圖解決這個問題(布爾_drawing),但它沒有工作。你可以幫我嗎? -Jakob

+0

當您使用'Iterator'這個數據結構不得更改底層的數據結構,否則你會得到這個'Exception'(一個'foreach'循環使用'背景中的迭代器')。一個簡單的解決方法是使用普通的'for'循環,但由於併發問題,這可能會跳過一些元素。 – Turing85

+0

好吧,這是最好的答案。我現在使用http://pastebin.com/vXA50Frz,它的工作原理。謝謝! – Jakob

回答

1

嘗試併發名單如CopyOnWriteArrayList

+0

修復了這個問題,一切正常。謝謝!所有粒子現在都很高興:https://i.imgur.com/0eWltuu.png – Jakob

+0

@Jakob請注意,這個類效率非常低,因爲它在每次寫入時創建一個新的列表副本。與使用這種「快速」解決方案相比,您會更好地同步操作。 – user1803551

+0

但是如何?我的解決方案(布爾_drawing)沒有工作。編輯:當前的解決方案需要太多的CPU功耗(i7-4790k @ 4,7GHz):https://i.imgur.com/OV5JQ2p.png – Jakob