不知道为什么我会收到这个例外。问题是有时在onClose
之前调用closeAllOpenSessions
。 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);
}
}
}
答案 0 :(得分:2)
在closeAllOpenSesions()
方法中,您将对openSessions
集合进行迭代,并针对其中的每个元素调用close()
,这当然会导致您的onClose()
openSessions
解雇方法。然后,您每次调用onClose()
方法时都会迭代并从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
这与以下情况没有什么不同:
ConcurrentModificationException
您不能同时迭代同一个集合的两个迭代器。如果这样做,如果内部循环删除外部循环期望迭代的元素,则将抛出openSessions
。
乍一看,我不明白为什么你需要在B.onClose()
内迭代B.onClose()
。为什么closeAllOpenSessions()
要负责关闭所有公开会话?不应该在{{1}}中完成吗?