【问题标题】:Getting java.util.ConcurentModificationError in collision detecton在碰撞检测中获取 java.util.ConcurrentModificationexcEption
【发布时间】:2014-03-07 18:51:19
【问题描述】:

在这里,我在for(Candy c2 : candylist) { 行中得到java.util.ConcurentModificationError。 谁能告诉我怎么了?我正在尝试检查两个链接列表中管理的几个图像的碰撞检测说

  • 第一个气球列表
  • 第二次火灾清单

这段代码是气球和火的碰撞检测:

public void collision(final Balloon mb1) {
    ImageView iv11 = mb1.getIv1();
    Rect r1 = new Rect(iv11.getLeft(), iv11.getTop(), iv11.getLeft() + iv11.getWidth(), iv11.getTop()+iv11.getHeight());
    for (Candy c2 : candylist) {
        if (c2 != null) {
            ImageView iv22 = c2.getIv2();
            if (iv22 != null) {
                Rect r2 = new Rect(iv22.getLeft(), iv22.getTop(), iv22.getLeft() + iv22.getWidth(), iv22.getTop()+iv22.getHeight());
                if (r1.intersect(r2)) {
                    runOnUiThread(new Runnable() {
                        public void run() {
                            mb1.getTt1().cancel();                  
                            if (mb1.isBursted() == false) {
                                mb1.setBursted(true);
                                update(mb1);                            
                            }
                        }
                    });
                }
            }
        }
    }
}

public void update(final Balloon mb1) {
    final int bp = balloonList.indexOf(mb1);

    if (bp != -1) {
        if (sound == true) {
            mp = MyUtils.playSound(R.raw.bur, Game.this);
        }

        final ImageView iv1 = mb1.getIv1(); 
        iv1.setImageResource(R.drawable.negate);
        iv1.setEnabled(false);
        Animation a1 = AnimationUtils.loadAnimation(Game.this, R.anim.fade);
        iv1.startAnimation(a1);
        TimerTask tt = mb1.getTt1();
        tt.cancel();
        TimerTask tt1 = new TimerTask() {
            public void run() {
                runOnUiThread(new Runnable() {
                    public void run() {
                        balloonList.set(bp, null);
                        al.removeView(iv1);
                    }
                });
            }
        };

        t1.schedule(tt1, 1200);
        missed++;
        score = score-10;

        if (music == true) {
            if (mp2 != null) {
                MyUtils.releaseSound(mp2);
            }
        }
        showscore();
        showExitDialog(score);
    }
}

堆栈跟踪:

03-08 00:07:14.326: E/AndroidRuntime(586): FATAL EXCEPTION: Timer-1
03-08 00:07:14.326: E/AndroidRuntime(586): java.util.ConcurrentModificationException
03-08 00:07:14.326: E/AndroidRuntime(586):  at java.util.LinkedList$LinkIterator.next(LinkedList.java:124)
03-08 00:07:14.326: E/AndroidRuntime(586):  at bitcream.candyhive.candy.Game.collision(Game.java:609)
03-08 00:07:14.326: E/AndroidRuntime(586):  at bitcream.candyhive.candy.Game$11.run(Game.java:229)
03-08 00:07:14.326: E/AndroidRuntime(586):  at java.util.Timer$TimerImpl.run(Timer.java:284)

【问题讨论】:

  • 如果您使用诸如 libgdx 之类的游戏引擎,那么您将不再遇到碰撞检测问题
  • 您是否在迭代时尝试更新列表,实际上我找不到这个@Shubhankar
  • 能否请您编辑代码并指定行。不知道我找不到行
  • 我在函数更新中更新我的链表,如果两个图像发生碰撞,我会在函数更新中从气球列表中删除一项,就像: balloonList.set(bp, null); al.removeView(iv1);
  • @Shubhankar 不要像这样删除元素。使用迭代器类方法 remove() 删除元素,那么您将不会遇到这种情况

标签: java android java.util.concurrent


【解决方案1】:

您的集合 candylist 在您对其进行迭代时被修改。

假设您的集合是线程安全的,您应该在迭代之前创建集合的副本。

for (Candy c2 : candylist.toArray(new Candy[0]))

【讨论】:

  • 只需要更正一次即可指定数组大小,否则会出现 arrayindexoutofbound 异常。谢谢。
  • 您可以指定一个大小为零的数组。 Javadoc 说 - “参数 a:如果足够大,则该集合的元素要存储到其中的数组;否则,为此目的分配相同运行时类型的新数组。”
  • 但它在我的情况下显示错误,正如 Stacktrace 中指定的那样,它在以下行中为我提供了 indexoutofboundexception:for (Candy c2 : candylist.toArray(new Candy[0]))
【解决方案2】:

这不是很明显。在获得iterator 之后,您不应以任何方式修改collection,除非通过迭代器自己的删除或添加方法。

虽然您还没有提供完整的代码,但我认为:

for (Candy c2 : candylist)

forEach 循环体的某个地方,您正在对candylist 进行结构性修改,因此您将获得ConcurrentModificationException

从堆栈跟踪中,我假设您使用 LinkedList 代替 candylist

根据LinkedListjavadoc:

如果列表在迭代器创建后的任何时间发生结构性修改,除了通过迭代器自己的 remove 或 add 方法之外的任何方式,迭代器都会抛出 ConcurrentModificationException。

所以不要使用 enhanced for 语句,它解析为:

for (I #i = Expression.iterator(); #i.hasNext(); )

我建议您通过 candylist 获取一个迭代器,并使用迭代器自己的删除或添加方法对其进行修改。

【讨论】:

  • 我没有投反对票,但我的问题是“您不应该在获得迭代器后修改集合”那么我们如何在迭代时更新列表??
  • @Youngistan 哦,我错过了“除了通过迭代器自己的删除或添加方法”的部分。我已经编辑了我的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-05
  • 2019-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多