【问题标题】:Way to use an ArrayList without ConcurrentModificationException(s)?在没有 ConcurrentModificationException(s) 的情况下使用 ArrayList 的方法?
【发布时间】:2023-04-03 08:53:01
【问题描述】:

JAVA

我的游戏中有一个 ArrayList 来存储游戏中的所有粒子。我有一个访问 ArrayList 以更新物理的更新方法,我有一个访问 ArrayList 以在屏幕上渲染粒子的渲染方法和一个 MouseClick 侦听器,当它检测到 MouseClick 时,它将向 ArrayList 添加一个新粒子。

我的问题是我不断收到 java.util.ConcurrentModificationException。这是因为当我同时单击它呈现并且两种方法都试图访问 ArrayList。有没有办法同时访问ArrayList(不同的数据类型?)。

一些代码可以帮助解决-

ArrayList 声明

ArrayList<Particle> ParticleList = new ArrayList<Particle>();

粒子类定义

public class Particle {

int x;
int y;
Color colour;
int type;
//0:wall
public Particle(int x,int y,Color colour,int type)
{
    this.x = x;
    this.y = y;
    this.colour = colour;
    this.type = type;
}`

渲染方法

for(Particle e : this.ParticleList)
{
g.fillRect(e.x, e.y, 1, 1);
}

【问题讨论】:

  • 如果您尝试在迭代期间添加/删除 2 件事:使用 ListIterator.remove/add 但除了在最后添加/删除之外它可能会很慢。您很可能需要重新设计数据结构

标签: java arrays collections arraylist


【解决方案1】:

更新:看来你没有多线程访问,所以我原来的答案不成立(为了完整起见,我会保留它)

ConcurrentModificationException 仅当您在迭代时从集合中添加或删除时才会出现在单个线程中。要解决此问题,请创建一个新集合,它是第一个集合的副本,然后添加到其中。


如果您的写入次数(点击次数)远少于读取次数,那么您可以使用 CopyOnWriteArrayList

否则您将不得不在迭代时进行同步。或获取副本 (List copy = new ArrayList(original))

【讨论】:

  • 所描述的问题不是多线程操作的结果,CoWArrayList 即使添加也有 O(n*n) ,粒子看起来很多而且会非常慢。由于问题似乎不是多线程同步不会解决问题。
  • @bestsss 我没有完全理解所描述的问题,这就是为什么我有一个“如果”和“否则”。添加到 COWAL 确实是最慢的操作,这就是为什么只有在有一些添加时才应该使用 if 的原因。此外,我仍然认为存在多线程访问。它看起来像带有事件线程和主线程的摇摆。
  • @Bozho,他无法通过点击等来描述它,多线程问题的一个常见问题是它们难以重现/描述。
  • @Liam E-p 然后显示代码.. 如果它不是多线程的,我相信问题很简单。
  • @Liam E-p 我在那里看不到任何列表迭代。异常发生在哪里?
【解决方案2】:

Swing 本身是隐式单线程的。您的点击和渲染应该在同一个线程上。如果您这样做,您将不会收到 ConcurrentModificationException,因为您只会呈现或处理点击。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 2021-12-12
    • 2021-02-16
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多