【问题标题】:Why does this gives me an error (Multi Thread or ArrayList)?为什么这会给我一个错误(多线程或 ArrayList)?
【发布时间】:2020-03-14 23:02:40
【问题描述】:

我有两个正在运行的线程,我需要控制子弹是否接触到敌人,但这给了我打印“s4”的问题。知道那里发生了什么吗?我是个初学者。我正在使用 Java。

ArrayList<Nemico> nemici= o_orda.getNemici();
        for (Nemico nemico : nemici) {
            if(Collisioni.ControllaCollisioni(o_navicella, nemico)){
                nemici.remove(nemico);
                this.o_navicella.vita-=10;



                break;
            }
            for (Proiettile pro : proiettili){
                System.out.println("s1");
                    if(Collisioni.CollsioniProiettile(pro, nemico)){
                        System.out.println("s2");
                        nemici.remove(nemico);
                        System.out.println("s3");
                        proiettili.remove(pro);
                        System.out.println("s4");
                        break;

                }
                    System.out.println("s5");
            }

            if(ControllaSconfitta()){
                this.giocON=false;
                Disegna();
            }
        }

这是代码,我相信它会对您有所帮助。 此代码位于一个函数中,该函数每 n 毫秒检查和更新一次所有内容。

感谢您的帮助

Exception in thread "Thread-7" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
    at java.util.ArrayList$Itr.next(ArrayList.java:851)
    at java.lang.Thread.run(Thread.java:745)

当碰撞发生时它会冻结游戏。

【问题讨论】:

  • 检查ConcurrentModificationExceptionArrayListfail-fast部分(迭代器,用于for-each循环)
  • 您可能应该使用带有真正迭代器的循环。然后,您可以使用迭代器在 ArrayList 中添加或删除。
  • 使用 getListIterator() 以获得最佳结果。
  • 好的,你能举例说明我的代码应该如何使用迭代器吗?谢谢

标签: java multithreading arraylist


【解决方案1】:

以下代码已更新为使用 Iterator.remove() 而不是 ArrayList.remove()。感谢@PeterRader 澄清了这些应该如何使用。


如果您打算在迭代 ArrayList 时对其进行修改,则不应使用 for-each 循环直接对其进行迭代。有两种替代方法,使用迭代器来避免遍历 ArrayList 本身,或者使用 Java 8 的 removeIf() 函数。

我将给出一个使用迭代器的简单(且经过测试)示例,然后尝试修改您的代码以执行相同的操作:

迭代器示例

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

public class IteratorExample{

     public static void main(String []args){

        ArrayList<Integer> arrList = new ArrayList<Integer>(Arrays.asList(1,2,3));

        // Get an Iterator to iterate over the Integers in arrList

        Iterator<Integer> iterator = arrList.iterator();

        // While iterator hasNext element, access this element with .next() and print it. 
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }


     }
}

修改代码以使用迭代器

对于此版本中的任何拼写错误或语法错误,我深表歉意 - 我无法对其进行测试,但鉴于它只是一小段代码,不应该有很多代码,希望您能够使用示例来纠正它们以上。 别忘了也导入 java.util.Iterator!

ArrayList<Nemico> nemici= o_orda.getNemici();

Iterator<Nemico> nemiciIterator = nemici.iterator();

while (nemiciIterator.hasNext()) {

    nemico = nemiciIterator.next();

    if(Collisioni.ControllaCollisioni(o_navicella, nemico)){
        nemiciIterator.remove(nemico);
        this.o_navicella.vita-=10;
        break;
    }

    Iterator<Proiettile> proIterator = proiettili.iterator();

    while (proIterator.hasNext()) {

        pro = proIterator.next();

        if(Collisioni.CollsioniProiettile(pro, nemico)){
            nemiciIterator.remove(nemico);
            proIterator.remove(pro);
            break;
        }
    }

    if(ControllaSconfitta()){
        this.giocON=false;
        Disegna();
        }
    }
    ...

资源

这是一个相关资源。这还包括一个使用 removeIf() 的示例! https://www.baeldung.com/java-concurrentmodificationexception.

【讨论】:

  • @PeterRader 谢谢你,虽然我不确定那是正确的。我不希望从迭代器中删除该项目,我希望将其从 ArrayList 本身(nemici)中删除,就像原始海报试图做的那样。 Iterator.next() 从迭代器中移除对象并返回它,因此不需要显式移除它(我什至不确定 Iterator.remove() 是一个方法)。从迭代器中删除对象仍然会将它们留在初始的 ArrayList 中,不是吗?你能澄清一下吗?
  • @PeterRader 嗨,彼得,非常感谢您的澄清——我没有意识到是这样的。我现在已经相应地更新了答案,希望现在是正确的。
  • 汤姆为您服务,很好的回答!
猜你喜欢
  • 2013-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 1970-01-01
  • 2012-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多