简体   繁体   English

ArrayList上的java.util.ConcurrentModificationException

[英]java.util.ConcurrentModificationException on ArrayList

I have a Server class and a Timer inside it which is supposed to clear dead clients (clients who crashed). 我有一个Server类和一个Timer,它应该清除死客户端(崩溃的客户端)。 I followed the example below by locking the collection when the Timer iterates over the users but I still get this exception (after I crash a connected client). 我按照下面的示例通过在Timer迭代用户时锁定集合但我仍然得到此异常(在我崩溃连接的客户端之后)。

http://www.javaperformancetuning.com/articles/fastfail2.shtml http://www.javaperformancetuning.com/articles/fastfail2.shtml

List<User> users;
List<User> connectedUsers;
ConcurrentMap<User, IClient> clients;

...

users = Collections.synchronizedList(new ArrayList<User>());
connectedUsers = new ArrayList<User>();
clients = new ConcurrentHashMap<User, IClient>();
timer = new Timer();
timer.schedule(new ClearDeadClients(), 5000, 5000);

...

class ClearDeadClients extends TimerTask {
    public void run() {
        synchronized (users) {
            Iterator<User> it = users.iterator();
            while (it.hasNext()) {
                User user = it.next(); // Throws exception
                if (!connectedUsers.contains(user)) {
                    users.remove(user);
                    clients.remove(user);
                }
            }
        }       

        connectedUsers.clear();
    }
}

You need to remove from the iterator not the collection. 您需要从迭代器中删除而不是集合。 It would look like this instead: 它看起来像这样:

Iterator<User> it = users.iterator();
while (it.hasNext()) {
    User user = it.next(); 
    if (!connectedUsers.contains(user)) {
         it.remove();
         clients.remove(user);
     }
}

You cannot modify a collection while iterating over it - unfortunately you do that here with users , and the ConcurrentModificationException is the result. 迭代时无法修改集合 - 不幸的是,您在此处与users一起执行此users ,并且结果是ConcurrentModificationException。 From ArrayList's own javadocs : 从ArrayList自己的javadocs

The iterators returned by this class's iterator and listIterator methods are fail-fast : if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException . 此类的iteratorlistIterator方法返回的iterator快速失败的 :如果在创建迭代器之后的任何时候对列表进行结构修改,除了通过迭代器自己的removeadd方法之外,迭代器将抛出ConcurrentModificationException Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future. 因此,在并发修改的情况下,迭代器快速而干净地失败,而不是在未来的未确定时间冒着任意的,非确定性行为的风险。

To fix this particular situation, you could instead use the Iterator's own remove() method, by replacing this line: 要解决这种特殊情况,您可以使用Iterator自己的remove()方法替换此行:

users.remove(user);

with

it.remove();

This latter operation removes from the collection the last element that the iterator returned. 后一个操作从集合中删除迭代器返回的最后一个元素。 (This usage avoids the exception because the iterator is aware of the change and is able to ensure it's safe; with external modifications the iterator has no way to know whether the state of its traversal is still consistent, and so fails fast). (这种用法避免了异常,因为迭代器知道更改并且能够确保它是安全的;通过外部修改,迭代器无法知道其遍历的状态是否仍然一致,因此快速失败)。

In some situations, this immediate removal may not be workable, in which case there are three alternative general approaches: 在某些情况下,这种立即删除可能不可行,在这种情况下,有三种可选的一般方法:

  1. Take a copy of the collection ( users in this case), iterate over the copy and remove elements from the original . 获取集合的副本(本例中为users ),遍历副本并从原始元素中删除元素。
  2. During iteration, build up a set of elements to remove, and then perform a bulk removal after iteration has completed. 在迭代期间,构建一组要删除的元素,然后在迭代完成后执行批量删除。
  3. Use an List implementation which can deal with concurrent modifications, like the CopyOnWriteArrayList 使用可以处理并发修改的List实现,例如CopyOnWriteArrayList

This is quite a common question - see also (for example) the loop on list with remove question for other answers. 这是一个非常常见的问题 - 另请参阅(例如) 列表中循环,并删除其他答案的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.util.ConcurrentModificationException - ArrayList - java.util.ConcurrentModificationException - ArrayList 带有自定义ArrayList的java.util.ConcurrentModificationException - java.util.ConcurrentModificationException with custom ArrayList 多线程ArrayList上的java.util.ConcurrentModificationException - java.util.ConcurrentModificationException on ArrayList in multi thread ArrayList处理中的java.util.ConcurrentModificationException - java.util.ConcurrentModificationException in ArrayList processing arraylist java.util.ConcurrentModificationException从其他类初始化 - arraylist java.util.ConcurrentModificationException initialize from other class 使用INDEX删除ArrayList中的元素,从而导致java.util.ConcurrentModificationException - Removing element in ArrayList using INDEX causing java.util.ConcurrentModificationException 从ArrayList中删除标记:java.util.ConcurrentModificationException - Remove the marker from the ArrayList: java.util.ConcurrentModificationException ArrayList迭代给出异常java.util.ConcurrentModificationException - ArrayList iteration gives exception java.util.ConcurrentModificationException 通过arraylist时抛出java.util.ConcurrentModificationException - java.util.ConcurrentModificationException thrown while going through arraylist 使用 ArrayList 和递归避免 java.util.ConcurrentModificationException - avoid java.util.ConcurrentModificationException using ArrayList and recursion
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM