Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-并发修改异常_Java_Multithreading_Exception_Concurrency - Fatal编程技术网

Java-并发修改异常

Java-并发修改异常,java,multithreading,exception,concurrency,Java,Multithreading,Exception,Concurrency,我收到以下代码的并发修改异常: for(Iterator<Tile> iter = spawner.activeTiles.iterator(); iter.hasNext();) { Tile tile = iter.next(); canvas.drawRect(tile, tile.getColor()); } for(Iterator iter=spawner.activeTiles.Itera

我收到以下代码的并发修改异常:

        for(Iterator<Tile> iter = spawner.activeTiles.iterator(); iter.hasNext();) {
            Tile tile = iter.next();
            canvas.drawRect(tile, tile.getColor());
        }
for(Iterator iter=spawner.activeTiles.Iterator();iter.hasNext();){
Tile-Tile=iter.next();
drawRect(tile,tile.getColor());
}
我知道在迭代过程中(在迭代过程中添加/删除)更改时,会发生并发修改。我也明白,在多线程处理时可能会发生这种情况,我认为这就是我的问题所在

在我的游戏中,我有一些运行在线程上的计时器。我有一个生成程序,它在每个刻度上为activeTiles添加值。然后我有两个计时器,一个用于淡入,一个用于淡出。在不放弃我的游戏的情况下,当淡出结束时,或者当玩家轻触互动程序时,互动程序基本上从列表中删除。因此,有一些情况下会从磁贴列表中删除磁贴:

for(Iterator<Tile> iter = spawner.activeTiles.iterator(); iter.hasNext();) {
                Tile tile = iter.next();

                if(tile.contains(x, y) && tile.equals(spawner.activeTiles.get(0))) {
                    vibrator.vibrate(50);

                    tile.setBroken(true);
                    score ++;
                    spawner.setTileDelayInfo();
                    iter.remove();
for(Iterator iter=spawner.activeTiles.Iterator();iter.hasNext();){
Tile-Tile=iter.next();
if(tile.contains(x,y)&&tile.equals(spawner.activeTiles.get(0))){
振动器。振动(50);
tile.setBroken(真);
分数++;
spawner.setTileDelayInfo();
iter.remove();
在每次新生成之前,它会删除所有失败的分幅:

private void removeFailedTiles() {
    for(Iterator<Tile> iter = activeTiles.iterator(); iter.hasNext();) {
        Tile tile = iter.next();

        if(tile.isFailed()) {
            iter.remove();
        }
    }
}
private void removedfailedtiles(){
for(迭代器iter=activeTiles.Iterator();iter.hasNext();){
Tile-Tile=iter.next();
if(tile.isFailed()){
iter.remove();
}
}
}

它几乎是随机发生的。所以我认为它与时间有关,但我对这种异常不熟悉,不知道该查找什么,也不知道为什么会发生这种情况。

多线程可能是
ConcurrentModificationException
的一个来源。当一个线程修改collect的结构时,可能会发生这种情况当另一个线程有一个
迭代器对其进行迭代时,这可能会导致应用程序出现意外状态,因为当一段代码需要一致的数据视图时,集合的状态会发生变化。这是在迭代
平铺
的集合时需要的

您需要同步对
activeTiles
集合的访问。任何在结构上修改此集合(添加或删除)或对其进行迭代的操作都必须在此集合上同步

在迭代或在结构上修改
activeTiles
的所有代码周围添加一个
synchronized(activeTiles)
块。这包括您在此处提供的所有3个代码片段

或者,您可以使与您的代码段相对应的3个方法同步


无论哪种方式,在另一个
线程完成其
syncrhonized
部分之前,没有任何其他
线程可以执行任何
synchronized
块,从而防止
ConcurrentModificationException
使用支持元素删除的
迭代器删除元素是不安全的,当您在另一个线程中迭代集合时


在迭代之前,请在activeTiles上的所有线程中获取一个。您可能希望使列表线程安全。请使用

请注意,在对该列表进行迭代时,必须对其进行同步:

synchronized (threadSafeActiveTiles) {
    for (Iterator<Tile> it = threadSafeActiveTiles.iterator(); it.hasNext();) {
        Tile tile = it.next();
        // ...
    }
}
synchronized(threadSafeActiveTiles){
for(Iterator it=threadSafeActiveTiles.Iterator();it.hasNext();){
Tile Tile=it.next();
// ...
}
}
然后,您可以安全地让多个线程修改列表,这似乎就是您的情况


Collections.synchronizedList()
返回的列表使您无需在该列表上的单个操作中使用同步块(如上),如
add(e)
size()
get(i)
等等…

好消息是:您在问题中找到了问题的根本原因-您不能让多个线程同时访问列表,除非它们都只是在阅读

您可以通过两种方式之一来解决这个问题,具体取决于代码的其余部分是如何操作的。最“正确”的方式是steffen的回答:任何列表访问都应该使用
synchronized
块进行保护,这包括在任何列表迭代的整个过程中保持锁定。请注意,如果这样做,您只需要做很少的工作在保持锁的同时尽可能多地调用侦听器—特别是,在保持锁的同时执行任何类型的侦听器回调都不是一个好主意


第二种选择是使用线程安全的,不需要任何外部同步,但是对列表的任何修改(添加/删除/替换调用)都会变得非常昂贵。

如果它“似乎是随机发生的”这可能是多线程问题。@Ata,他使用的是迭代器,不是同一个问题。事实上,使用迭代器是这个问题的答案,所以他这样做是正确的!添加synchronized on函数将同步对函数的访问,而不是对函数中使用的数据结构的访问。两个不同的rent函数正在访问相同的列表。@Ata在这些方法上添加
synchronized
将锁定对象实例,该对象实例在每个线程中都是相同的对象实例。效果与
synchronized(activeTiles)中的效果相同
;迭代或修改
activeTiles
的代码一次只能由一个线程执行。是的,所有迭代
activeTiles
或在结构上修改它的代码都必须是
同步的
。语法是什么?我从未使用过同步的before@KyleJensen有和。synchr如果在列表上迭代,onizedList是不够的,因为在整个迭代过程中没有锁,所以仍然可以获得Concurren
synchronized (threadSafeActiveTiles) {
    for (Iterator<Tile> it = threadSafeActiveTiles.iterator(); it.hasNext();) {
        Tile tile = it.next();
        // ...
    }
}