添加和删​​除元素的元素

时间:2015-05-31 11:21:06

标签: java arraylist concurrentmodification

我是Java新手,我现在制作的游戏中玩家必须吃一些饼干。这些cookie是ArrayList的元素。这个ArrayList由两个线程修改: -one迭代它并删除已经吃过的cookie,使用Iterator.remove() - 每5秒向ArrayList添加一个cookie

有时候我得到一个ConcurrentModificationException,我知道它是因为Iterator.remove()的行为是未指定的,如果在迭代进行过程中以任何其他方式修改了底层集合" ;,如Sun的Java教程中所述。我该怎么办?

编辑:用

更新代码
List<Cupcake> cake = Collections.synchronizedList(new ArrayList<Cupcake>());

这是Spawner:

public class CupcakeSpawner extends Thread {
    private Background back;

    public CupcakeSpawner(Background back) {
        this.back = back;
    }

    public void run() {
        while(true) {
            if(back.getCake().size() < 15)
                back.getCake().add(new Cupcake());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

我的更新方法:

public void update() {
    List<Cupcake> cake = back.getCake();
    Iterator<Cupcake> itrC = cake.iterator();
    while(itrC.hasNext()) {
        Cupcake cupcake = (Cupcake)(itrC.next());
        checkCollisionCup(cupcake);
        if(cupcake.isEaten()) 
                itrC.remove();
        }
    }
}

3 个答案:

答案 0 :(得分:1)

ArrayList不是List的线程安全实现。

使用CopyOnWriteArrayList代替 - 如果在迭代时添加元素,则不会引发爆炸。

答案 1 :(得分:0)

正如@Bohemian所说,ArrayList不是线程安全的。

最好使用:

List list = Collections.synchronizedList(new ArrayList());

然后你要打电话给Iterator.remove()

synchronized (list) {
  Iterator.remove() 
}

希望这会对你有所帮助。

See this

public class CupcakeSpawner extends Thread {
private Background back;

public CupcakeSpawner(Background back) {
    this.back = back;
}

public void run() {
    List cakes = back.getCake();
    while(true) {
        if(cakes.size() < 15){
            synchronized (cakes) {
                 cakes.add(new Cupcake());
            }
        }
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
      }
   }
}

答案 2 :(得分:0)

如果基础数组发生了变化,那么我们就不能使用Iterator的{​​{1}}:

ArrayList

当然,对于线程也是如此。

所以在你的情况下,你正在检查吃过的纸杯蛋糕(去除它们),同时还要在同一个系列中添加新的纸杯蛋糕。你所经历的是一种所谓的竞争条件。

解决此问题的一种方法是使用@Bohemian建议的public static void main(String[] args) { List<Object> l = new ArrayList<>(); Iterator<Object> i = l.iterator(); l.add(new Object()); try { System.out.println("I've added " + i.next()); } catch (ConcurrentModificationException e) { System.out.println("Nooo!!!"); } } ,但我不推荐它,因为每次修改都会导致创建一个新数组,这是一个性能开销(和内存)如果&#34;旧&#34;数组仍然被引用,例如由于CopyOnWriteArrayList实例,则会出现问题。

解决此问题的另一种方法是在更新方法中使用count for循环。

Iterator

重要提示:使用此循环计数,您应该使用@Aalkhodiry建议的同步列表。

Fwiw:还有比这更多的线程......