解决ConcurrentModificationException

时间:2012-02-10 08:28:12

标签: java thread-safety concurrentmodification

我正在写一个小游戏,屏幕上有很多圈子 我在两个主题中管理圈子如下:

public void run() {
    int stepCount = 0;
    int dx;
    int dy;
    while (m_threadTrap){
        dx = 0;
        dy = 0;

        synchronized (m_circles) {
            for (Iterator<Circle> it = m_circles.iterator(); it.hasNext();){
                Circle c = it.next(); //Exception thrown here.
                if (c.getDirX() != 0)
                    if (stepCount % c.getDirX() == 0){
                        dx = 1;
                    }
                if (c.getDirY() != 0)
                    if (stepCount % c.getDirY() == 0){
                        dy = 1;                 
                    }

                c.move(dx, dy); 
            }
        }
        if (stepCount == 150000){
            stepCount = 0;
        }
        stepCount++;
    }
}

圈子的ArrayList中的m_circles。

以下主题:

public void run() {
    while (m_threadTrap){
        int topPosition;
        int bottomPosition;
        int leftPosition;
        int rightPosition;
        ArrayList<Circle> removedCircles = new ArrayList<Circle>();
        synchronized (m_circles.getCircles()) {
            for (Iterator<Circle> it = m_circles.getCircles().iterator(); it.hasNext();){
                Circle c = it.next();

                // Some calculation to evaluate which circles should be removed
                    removedCircles.add(c);
                }
            }
        }
        try{
            Thread.sleep(25);
        }
        catch (Exception e) { }

        m_circles.getCircles().removeAll(removedCircles);

        if (m_circles.getCircles().size() < 30)
            m_circles.addNewCircle();

        repaint(); 
    }
}

我的问题是我在

行获得了ConcurrentModificationException
Circle c = it.next();

在第一个帖子中。起初我尝试使用foreach循环遍历ArrayList,这给了我同样的例外 在研究了这个例外之后,我看到了两个解决方案:
 1.将访问集合的部分放在同步块中  2.使用集合的Iterator对象 他们俩都没有为我解决。

2 个答案:

答案 0 :(得分:1)

要使synchronized() {}块有效,对受保护对象的所有访问必须包含在同步块中。你可能忘了包装一些访问权。

另一个“问题”是ConcurrentModificationException也意味着它在同一个线程中同时修改了 。例如,如果在遍历集合时从集合中删除元素,则可能会出现此异常。 (作为例外,您可以通过迭代器本身安全地删除元素)

答案 1 :(得分:1)

ConcurrentModificationException意味着您正在迭代一个集合,并且在迭代时,某人(当前线程或另一个)修改了底层集合而不使用Iterator.remove()。每当您在Iterator上调用一个操作时,它都会检查底层集合是否未被更改。使用foreach不会改变任何东西,因为它使用Iterator来执行循环。

您的解决方案是:

  1. 创建一个新集合:

    for(Circle c:new ArrayList(m_circles.getCircles())。iterator()){        //一些计算来评估应删除哪些圆圈        removedCircles.add(C); }

  2. 无论何时修改或访问集合,
  3. 或同步同一对象上的两个线程(您在不同对象上同步,因此它不会执行任何操作)

相关问题