这为什么会报错(多线程或ArrayList)?

huangapple go评论76阅读模式
英文:

Why does this gives me an error (Multi Thread or ArrayList)?

问题

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

This is the code, I'm sure it will help you.
This code is in a function that checks and updates everything every n milliseconds.

Thanks for the help

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)

and it freezes the game when the collision happens.


<details>
<summary>英文:</summary>

I have two threads which are running and I need to control if the bullet is touching the enemy but it gives me this problem where I printed &quot;s4&quot;. Any idea what happened there? I&#39;m quite a beginner. I&#39;m using 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(&quot;s1&quot;);
                if(Collisioni.CollsioniProiettile(pro, nemico)){
                    System.out.println(&quot;s2&quot;);
                    nemici.remove(nemico);
                    System.out.println(&quot;s3&quot;);
                    proiettili.remove(pro);
                    System.out.println(&quot;s4&quot;);
                    break;
                    
            }
                System.out.println(&quot;s5&quot;);
        }
       
        if(ControllaSconfitta()){
            this.giocON=false;
            Disegna();
        }
    }

This is the code, I&#39;m sure it will help you. 
This code is in a function that checks and update everything every n millisecond.

Thanks for the help 

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)

and it freeze the game when the collsion happens.




</details>


# 答案1
**得分**: 1

_以下代码已经更新以使用Iterator.remove(),而不是ArrayList.remove()。感谢@PeterRader澄清了它们的使用方法。_

---

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

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

**迭代器示例**
```java
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));

        // 获取一个迭代器以迭代arrList中的整数

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

        // 当迭代器有下一个元素时,使用.next()访问此元素并将其打印出来。
        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();
        this.o_navicella.vita -= 10;
        break;
    }

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

    while (proIterator.hasNext()) {

        pro = proIterator.next();

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

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

资源

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

英文:

The below code has been updated to use Iterator.remove() instead of ArrayList.remove(). Thank you to @PeterRader for clarifying how these should be used.


If you are intending to modify an ArrayList while iterating over it, you should not use a for-each loop to iterate over it directly. There are two alternative approaches, using an iterator to avoid iterating over the ArrayList itself, or using Java 8's removeIf() function.

I will give a simple (and tested) example of using an iterator, and then attempt to modify your code to do the same thing:

Iterator Example

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

public class IteratorExample{

     public static void main(String []args){
         
        ArrayList&lt;Integer&gt; arrList = new ArrayList&lt;Integer&gt;(Arrays.asList(1,2,3));
        
        // Get an Iterator to iterate over the Integers in arrList
        
        Iterator&lt;Integer&gt; iterator = arrList.iterator();
        
        // While iterator hasNext element, access this element with .next() and print it. 
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        
        
     }
}

Modifying your code to use an iterator

Apologies for any spelling mistakes or syntax errors in this version - I have been unable to test it, but given it's only a small piece of code there shouldn't be many and hopefully you will be able to remedy them using the example above. Don't forget to import java.util.Iterator too!

ArrayList&lt;Nemico&gt; nemici= o_orda.getNemici();

Iterator&lt;Nemico&gt; 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&lt;Proiettile&gt; 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();
        }
    }
    ...

Resources

Here is a relevant resource. This also includes an example of using removeIf()! https://www.baeldung.com/java-concurrentmodificationexception.

huangapple
  • 本文由 发表于 2020年3月15日 07:02:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/60688124.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定