首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >意外ConcurrentModificationException

意外ConcurrentModificationException
EN

Stack Overflow用户
提问于 2014-05-30 00:58:21
回答 1查看 125关注 0票数 1

不知道为什么我会得到这个例外。问题是,有时onClosecloseAllOpenSessions之前被调用。onClose正常工作,从_openSessions中移除指定的元素。但是,当closeAllSessions被调用时,当我们试图在_openSessions.上循环时会生成一个ConcurrentModificationException

当我注释掉remove语句时,不会出现异常。考虑到这两个操作是如何被同一个互斥保护的,我不知道为什么会发生这种情况。我遗漏了什么?

代码语言:javascript
复制
class B
{
    protected void onClose(Session session, List<WebSocketSessionStateful> openSessions) throws IOException
    {

        Iterator<WebSocketSessionStateful> openSessionsElements = openSessions.iterator();
        while(openSessionsElements.hasNext())
        {
            WebSocketSessionStateful openSession = openSessionsElements.next();
            if(session.equals(openSession.getSession()))
            {
                openSessionsElements.remove(); // comment me out to not throw exception
                return;
            }
        }
    }

    protected static void closeAllOpenSessions(List<WebSocketSessionStateful> openSessions) throws IOException
    {

        for(WebSocketSessionStateful openSession : openSessions) // exception generated here
        {
            openSession.getSession().close(new CloseReason(CloseReason.CloseCodes.GOING_AWAY, ""));
        }
    }
}

class A extends B
{
    private static final Object _endpointOperationMutex = new Object();

    private static final List<WebSocketSessionStateful> _openSessions = new ArrayList<WebSocketSessionStateful>();

    public void onClose(Session session, EndpointConfig config) throws IOException
    {
        synchronized (_endpointOperationMutex)
        {
            super.onClose(session, _openSessions);
        }
    }

    static void closeSessions() throws IOException
    {
        synchronized (_endpointOperationMutex)
        {
            WebSocketEndpointBase.closeAllOpenSessions(_openSessions);
        }
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-30 01:10:29

closeAllOpenSesions()方法中,迭代openSessions集合,并对其中的每个元素调用close(),这当然会触发onClose()方法。然后,通过每次调用onClose()方法从onClose()中迭代和删除--这就是并发修改的来源。

您可以更清楚地将问题概念化如下:

代码语言:javascript
复制
Iterator outerLoop = coll.iterator(); 
while (outerLoop.hasNext) { 
    Iterator innerLoop = coll.iterator(); 
    while (innerLoop.hasNext()){ 
        innerLoop.remove(); //ConcurrentModificationException
     }
 }

这与以下几点并无不同:

代码语言:javascript
复制
 for (Object o : coll)
     for (Object p : coll) 
         if (p.someBoolean()) remove(p); //ConcurrentModificationException

不能让两个迭代器同时迭代同一个集合。如果您这样做了,如果内环删除了外部循环期望迭代的元素,则会引发ConcurrentModificationException

乍一看,我不明白为什么需要在openSessions中迭代B.onClose()。为什么B.onClose()要负责关闭所有开放的会话?难道不应该用closeAllOpenSessions()来做吗?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23945433

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档