JAVA java.util.ConcurrentModificationException

时间:2014-12-18 07:09:18

标签: java

我正在尝试创建简单的JAVA程序。但自从去年以来,我遇到了这个问题,我无法解决。

public void receiveUpdate(ArrayList<Connection> connections) {

    for(Connection senderConnection : connections) {

        for(Connection receiverConnection : this.connections) {

            if(senderConnection.getDestination() == receiverConnection.getDestination()) {

                if(senderConnection.getDistance() + 1 < receiverConnection.getDistance()) {

                    senderConnection.setEnabled(false);
                    senderConnection.setDistance(senderConnection.getDistance() + 1);

                    this.connections.remove(receiverConnection);
                    this.connections.add(senderConnection);
                }
            }
        }

        senderConnection.setEnabled(false);
        senderConnection.setDistance(senderConnection.getDistance() + 1);

        this.connections.add(senderConnection);
    }
}

在这种方法中我总是得到错误:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at router.Router.receiveUpdate(Router.java:56)
    at router.Router.sendUpdate(Router.java:49)
    at loader.Loader.notifyNetworkChanges(Loader.java:61)
    at loader.Loader.main(Loader.java:102)

我注意到,如果我评论阻止,那么例外情况就不会出现:

senderConnection.setEnabled(false);
senderConnection.setDistance(senderConnection.getDistance() + 1);

this.connections.add(senderConnection);

谁能告诉我,问题出在哪里?

4 个答案:

答案 0 :(得分:2)

ConcurrentModificationException当不允许进行此类修改时,检测到并发修改对象的方法可能抛出此异常。 问题出在这里

this.connections.remove(receiverConnection);

当不允许进行此类修改时,检测到对象的并发修改的方法可能抛出此异常。 例如,一个线程通常不允许修改Collection而另一个线程正在迭代它。通常,在这些情况下,迭代的结果是不确定的。如果检测到此行为,某些Iterator实现(包括JRE提供的所有通用集合实现的实现)可能会选择抛出此异常。执行此操作的迭代器称为失败快速迭代器,因为它们快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。

请注意,此异常并不总是表示某个对象已被另一个线程同时修改。如果单个线程发出违反对象合同的一系列方法调用,则该对象可能会抛出此异常。例如,如果线程在使用失败快速迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。

检查this

要解决您的问题,您需要使用Iteratorremove()这样的方法

Iterator<String> connectionsIterator = connections.iterator();

while (connectionsIterator.hasNext()) {

    if (senderConnection.getDistance() + 1 < receiverConnection.getDistance()){

        connectionsIterator.remove();
// add the connection to another list other than this.connections.add(senderConnection);
// then when you finish add them back the this.connections
// so you avoid modifying this.connections
   }
} 

答案 1 :(得分:1)

实际上,您正在迭代时修改集合。

this.connections.remove(receiverConnection);
this.connections.add(senderConnection);

使用Iterator并致电remove()

Iterator<String> iter = connections.iterator();

while (iter.hasNext()) {

    if (someCondition)
        iter.remove();
}

使用Iterator删除方法而不是ArrayList

答案 2 :(得分:0)

您正在循环浏览this.connections并在内部尝试从this.connections移除此java.util.ConcurrentModificationException。更改代码以使用迭代器。

答案 3 :(得分:0)

如果您正在修改(例如删除)您正在循环的相同列表,那么您一定会得到ConcurrentModificationException

您可以使用提及的@ ankur-singhal迭代器,也可以制作列表的深层副本并从该副本中删除。然后,您可以指定原始列表的引用以指向具有修改的新引用。

另一个&#34;贪心&#34;方法(但不使用迭代器)将保留所有项目在另一个新列表中删除,并在结束for循环后调用removeAll(listOfConnectionsToBeRemoved),例如:

在for循环之前

ArrayList<Connection> connectionsToBeRemoved = new ArrayList<Connection>();
在你的for循环中

connectionsToBeRemoved.add(receiverConnection)
结束你的for循环后

this.connections.removeAll(connectionsToBeRemoved)

*您可以对要添加的连接执行相同操作。将它们保存在新列表中,然后将它们全部添加到连接列表中。