Hello World

吞风吻雨葬落日 欺山赶海踏雪径

0%

JDK1.4 的ConcurrentModificationException异常

JDK1.4 的ConcurrentModificationException异常处理记录

问题代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* @version 1.0 缓存用户信息的工具类。
*/
public class PrivilegeManager extends AbstractDomainEntity {

static final long serialVersionUID = 1288L;

/**
* 缓存用户信息的HashMap。 Key为UID,Value为EGISStaff
*/
//private static Map usersCacheMap = Collections.synchronizedMap(new HashMap());
private static Map usersCacheMap = new HashMap();
private Object o = new Object();
/**
* @roseuid 43BEBB810000
*/
public PrivilegeManager() {

}

public void setEGISStaff(EGISStaff staff) {
usersCacheMap.put(staff.getTheEGISStaffDTO().getUid(), new CacheRecord(
staff));
}

public EGISStaff getEGISStaffByUID(String uid) {
CacheRecord cachestaff = (CacheRecord) usersCacheMap.get(uid);
if (cachestaff != null) {
if (System.currentTimeMillis() - cachestaff.getCreateTime() > 5 * 60 * 1000) {
usersCacheMap.remove(uid);
return null;
} else {
return (EGISStaff) cachestaff.getValue();
}
} else
return null;

}

public void removeEGISStaffByUID(String uid) {
synchronized (o) {
usersCacheMap.remove(uid);
}
}

/**
* 获取缓存中所有的用户信息
* @return 包含若干EGISStaffDTO的List
*/
public List getAllEGISStaffs()
{
List staffs = new ArrayList();
//List removableUsers = new ArrayList();
synchronized (o) {
Set keysSet = usersCacheMap.keySet();
Iterator keysIterator = keysSet.iterator();

// 获取缓存中所有用户,若缓存时间超过5分钟则不获取
while (keysIterator.hasNext()) {
String uid = (String) keysIterator.next();
CacheRecord cachestaff = (CacheRecord) usersCacheMap.get(uid);
if (cachestaff != null) {
//if (System.currentTimeMillis() - cachestaff.getCreateTime() > 5 * 60 * 1000) {
// removableUsers.add(uid);
//}
//else {
EGISStaffDTO staff = ((EGISStaff) cachestaff.getValue()).getTheEGISStaffDTO();
staffs.add(staff);
//}
}
}
// 将缓存时间超过5分钟的用户清除出缓存,这里要单独拿出来删除,不能再循环里面,否则会报java.util.ConcurrentModificationException
//for (int i = 0; i < removableUsers.size(); i++)
// usersCacheMap.remove(removableUsers.get(i));
}

return staffs;
}
}

异常信息

1
2
3
4
5
com.paic.pafa.core.exceptions.PafaRuntimeException: EJB Exception: ; nested exception is: 
javax.ejb.EJBException: EJB Exception: : java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:782)
at java.util.HashMap$KeyIterator.next(HashMap.java:818)
at com.palic.egis.support.privilege.common.util.PrivilegeManager.getAllEGISStaffs(PrivilegeManager.java:76)

异常代码:String uid = (String) keysIterator.next();

private static Map usersCacheMap = new HashMap();
这里在迭代HashMap的KeySet的时候其他线程修改了此HashMap的内容。应该是public EGISStaff getEGISStaffByUID(String uid)中导致的。
修改方案:

1、两个方法都加上同步机制
2、换用 Collections.synchronizedMap(new HashMap()) ,因为是1.4的JDK,需要引入其他JAR包。
3、iterator 的时候删除。iterator可以保证数据一致性。