final Map<String, List<IoSession>> pidSessions = new ConcurrentHashMap<String, List<IoSession>>();
//该函数设置司机在线
private void setDidOnline(String did, IoSession session) {
if (this.didSessions.containsKey(did)) {
List<IoSession>list = this.didSessions.get(did);
for(IoSession ioss:list){ //这行代码老是抛出 ConcurrentModificationException 异常
if(ioss.getId() == session.getId()){
return ;
}
else{
list.add(session);
}
}
}
session.setAttribute(SESSION_KEY, did);
List<IoSession>list = new ArrayList<IoSession>();
list.add(session);
this.didSessions.put(did, list);
}
后来一运行就抛异常,,,,,,,
一直抛ConcurrentModificationException
看这个异常知道是线程安全导致,,,但是我在setDidOnline加了同步关键字,,还是没有效果。。。。。。
后来经高人指点,,,,,才知道自己犯了愚蠢的错误
for(IoSession ioss:list){ //这里迭代的时候会检查list长度是否被修改
if(ioss.getId() == session.getId()){
return ;
}
else{
list.add(session);//这里修改了list的长度
}
}
单个线程却导致了这个愚蠢的问题,,,,,,,,,,亏我写了这么多年的代码,,,,,
解决方案很简单,,,将List改成ConcurrentHashMap即可。
private void setDidOnline(String did, IoSession session) {
if (this.didSessions.containsKey(did)) {
Map<Long, IoSession> mapSessions = this.didSessions.get(did);
if (mapSessions.containsKey(session.getId())) {
return;
} else {
mapSessions.put(session.getId(), session);
}
}
session.setAttribute(SESSION_KEY, did);
Map<Long, IoSession> mapSessions = new ConcurrentHashMap<Long, IoSession>();
mapSessions.put(session.getId(), session);
this.didSessions.put(did, mapSessions);
}
private final Map<String, Map<Long, IoSession>> didSessions = new ConcurrentHashMap<String, Map<Long, IoSession>>();
分析原因:
1 对list iterator的时候,,,list节点是不允许修改的(iterator remove方法除外)
2 没有细看Iterator源码,,因为心急只是大概猜测下是并发问题,,,这个是程序员修养的问题。遇到问题,,对一些错误不是非常明确,要心平气和把源码看通,,,这样问题就会解开
方案2:
使用CopyOnWriteArrayList 替代 arraylist,因为写array的场景很少,,,大部分都是读操作