不知道为什么我要得到这个例外。问题是有时onClosecloseAllOpenSessions之前被调用。 onClose正常运行,从_openSessions中删除​​指定的元素。但是,当我们尝试循环遍历closeAllSessions时,调用ConcurrentModificationException时会生成_openSessions.

当我注释掉remove语句时,不会发生异常。考虑到这两个操作是如何用同一个互斥锁保护的,我不确定为什么会这样。我想念什么?

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);
        }
    }

}

最佳答案

在您的closeAllOpenSesions()方法中,您要遍历openSessions集合,并针对其中的每个元素调用close(),这当然会导致onClose()方法被触发。然后,每次调用该openSessions方法时,也要遍历onClose()并从ConcurrentModificationException中删除​​-这是您进行并发修改的地方。

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

Iterator outerLoop = coll.iterator();
while (outerLoop.hasNext) {
    Iterator innerLoop = coll.iterator();
    while (innerLoop.hasNext()){
        innerLoop.remove(); //ConcurrentModificationException
     }
 }


这与以下内容没有什么不同:

 for (Object o : coll)
     for (Object p : coll)
         if (p.someBoolean()) remove(p); //ConcurrentModificationException


您不能有两个迭代器同时对同一个集合进行迭代。如果这样做,如果内部循环删除了外部循环预期要迭代的元素,则会抛出openSessions

乍一看,我不明白为什么需要在B.onClose()中遍历B.onClose()closeAllOpenSessions()为什么要负责关闭所有打开的会话?那不是在中完成吗?

10-04 14:04