Java 解决ConcurrentModificationException

Java 解决ConcurrentModificationException,java,thread-safety,concurrentmodification,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

我正在写一个小游戏,其中有许多圆圈在屏幕上移动。
我在两个线程中管理圆圈,如下所示:

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++;
    }
}
在第一个线程中。起初,我尝试使用foreach循环遍历ArrayList,这给了我相同的异常。
在研究了一下这个异常之后,我看到了两个解决方案:
1.将访问集合的部分放入同步块中。
2.使用集合的迭代器对象。
他们都没有为我解决这个问题。

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


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

ConcurrentModificationException表示您正在对集合进行迭代,并且在迭代过程中,有人(当前线程或另一个线程)修改了基础集合,而没有使用
迭代器.remove()
。无论何时调用迭代器上的操作,它都会检查底层集合是否已更改。使用foreach不会改变任何事情,因为它使用迭代器来执行循环

您的解决方案是:

  • 创建新集合:

    for(圆c:newArrayList(m_circles.getCircles()).iterator()){ //一些计算来评估哪些圆应该被删除 删除圆圈。添加(c); }

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


  • 非常感谢,实际上还有一个接入点我忘了包装。
    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(); 
        }
    }
    
    Circle c = it.next();