为什么我的applet的paint方法抛出一个ConcurrentModificationException

时间:2012-06-02 21:49:00

标签: java concurrency applet awt

这是我的applet类:

package DavidPackages.Prototypes.Samples.BubblesV2SSCCE;

import java.applet.Applet;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.Random;

public class BubbleAppletV2SSCCE extends Applet implements Runnable{

    private Thread thread;
    private ArrayList<Ellipse2D> circles;

    public void init(){
        //Initialize bubbles with one entry so that we have a bubble to start out with
        Random r = new Random();
        circles = new ArrayList<Ellipse2D>();
        circles.add(new Ellipse2D.Float(5, 5, 15, 15));

        thread = new Thread(this);
        thread.start();
    }

    public void run(){
        while(true){

            update();
            repaint();

            try{
                Thread.sleep(10);
            }catch(InterruptedException ie){
                ie.printStackTrace();
            }
        }
    }

    private void update(){
        circles.add(new Ellipse2D.Float(5, 5, 15, 15));
    }

    public void paint(Graphics graphics){
        for(Ellipse2D circle : circles){
           ((Graphics2D) graphics).draw(circle);
        }
    }

    public void stop(){}
}

这是堆栈跟踪:

Exception in thread "AWT-EventQueue-1" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)
at java.util.AbstractList$Itr.next(AbstractList.java:420)
at DavidPackages.Prototypes.Samples.BubblesV2SSCCE.BubbleAppletV2SSCCE.paint(BubbleAppletV2SSCCE.java:43)
at sun.awt.RepaintArea.paintComponent(RepaintArea.java:276)
at sun.awt.RepaintArea.paint(RepaintArea.java:241)
at apple.awt.ComponentModel.handleEvent(ComponentModel.java:268)
at java.awt.Component.dispatchEventImpl(Component.java:4159)
at java.awt.Container.dispatchEventImpl(Container.java:2068)
at java.awt.Component.dispatchEvent(Component.java:3918)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:501)
at java.awt.EventQueue.access$000(EventQueue.java:80)
at java.awt.EventQueue$1.run(EventQueue.java:462)
at java.awt.EventQueue$1.run(EventQueue.java:461)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:84)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:95)
at java.awt.EventQueue$2.run(EventQueue.java:476)
at java.awt.EventQueue$2.run(EventQueue.java:475)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:84)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:473)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

我的代码中唯一的调用是:

    at DavidPackages.Prototypes.Samples.BubblesV2SSCCE.BubbleAppletV2SSCCE.paint(BubbleAppletV2SSCCE.java:43) 

就是这一行:

        for(Ellipse2D circle : circles){

更多详情:

  • 我在IntelliJ IDEA 10.5.4
  • 中运行此功能
  • 我在运行OSX 10.5.8的Mac上运行它
  • 当泡泡中存在更多泡泡实例时,更有可能抛出异常
  • 当applet的多个实例正在运行时,更有可能抛出异常

我很困惑,因为我看不到我是如何修改气泡的内容,而控制是在for循环中。

有没有人有任何想法?

奖金问题:

  • 我的目的是最终创建一个在某人机器上运行的游戏,而不是在Web浏览器中运行。除了applet之外,我应该使用什么?
  • 我应该使用什么而不是AWT?

关于那里的第二个红利问题。我发现this article表示:

  

AWT提供了丰富的图形环境,尤其是在Java V1.2及更高版本中。通过Graphics2D对象,Java2D和Java3D服务,可以创建许多功能强大的图形应用程序,例如绘图和图表包,以及与JavaSound相结合的竞争性交互式游戏。

这让我相信AWT确实适合我。或者作者错了?这篇文章是从2006年开始的,所以它有点过时但并不多。

更新(原始帖子中没有的内容):

  • 已删除注释掉的长代码
  • 更新了我的示例
  • 添加红利问题
  • 从比较AWT和Swing和SWT
  • 的文章中添加了引用

1 个答案:

答案 0 :(得分:3)

您不是在paint方法中更改气泡的内容,而是在run方法中更改它们,并且该方法在单独的线程中执行。这就解释了为什么你不总是得到那个例外,它只发生在你正在改变另一个线程中的列表气泡的同时执行paint时。