不知道为什么我要得到这个例外。问题是有时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);
}
}
}
最佳答案
在您的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()
为什么要负责关闭所有打开的会话?那不是在中完成吗?