不知道为什么我会得到这个例外。问题是,有时onClose在closeAllOpenSessions之前被调用。onClose正常工作,从_openSessions中移除指定的元素。但是,当closeAllSessions被调用时,当我们试图在_openSessions.上循环时会生成一个ConcurrentModificationException
当我注释掉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);
}
}
}发布于 2014-05-30 01:10:29
在closeAllOpenSesions()方法中,迭代openSessions集合,并对其中的每个元素调用close(),这当然会触发onClose()方法。然后,通过每次调用onClose()方法从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()来做吗?
https://stackoverflow.com/questions/23945433
复制相似问题