解决 ConcurrentModificationException

发布于 2025-01-04 10:41:10 字数 2037 浏览 0 评论 0原文

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

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对象。
他们都没有为我解决这个问题。

I am writing a little game which has many circles moving on the screen.
I am managing the circles in two threads as following:

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++;
    }
}

m_circles in an ArrayList of Circles.

And the following Thread:

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

My problem is that I get ConcurrentModificationException at the line

Circle c = it.next();

in the first thread. At first I tried going over the ArrayList with a foreach loop and this gave me the same exception.
After researching a bit on this exception I saw two solutions:
1. Putting the part which accesses the collection in a synchronized block.
2. Using the Iterator object of the collection.
Neither of them solved it for me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

始终不够 2025-01-11 10:41:11

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

您的解决方案是:

  1. 创建一个新集合:

    for (Circle c: new ArrayList(m_circles.getCircles()).iterator()) {
    // 一些计算来评估哪些圆应该被删除
    删除了Circles.add(c);
    }

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

ConcurrentModificationException means that you are iterating over a collection and, while iterating, someone (the current thread or another one) modified the underlying collection without using Iterator.remove(). Whenever you invoke an operation on the Iterator it checks that the underlying collection has not been changed. Using a foreach does not change a thing, since it uses an Iterator to perform the loop.

Your solution are:

  1. create a new collection:

    for (Circle c: new ArrayList(m_circles.getCircles()).iterator()) {
    // Some calculation to evaluate which circles should be removed
    removedCircles.add(c);
    }

  2. or synchronize both threads on the same object (you synchronize on different objects, therefore it does not do anything) whenever you are modifying or accessing the collection

心如狂蝶 2025-01-11 10:41:10

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

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

For a synchronized() {} block to be effective, all accesses to the protected objects must be wrapped in synchronized blocks. You probably forgot to wrap some access.

Another "gotcha" is that ConcurrentModificationException can also mean that it was concurrently modified in the same thread. For example, if you remove an element from a collection while traversing it, you may get this exception. (As an exception, you can safely remove elements via the iterator itself)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文