ConcurrentModificationException异常分析与解决
1、场景重现,制造ConcurrentModificationException异常
@Test
public void ConcurrentModificationExceptionTest() {
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 800);
jsonObject.put("msg", "msg");
jsonArray.add(jsonObject);
for (Object item : jsonArray) {
JSONObject json = JSON.parseObject(JSON.toJSONString(item));
if (Objects.equals(json.getInteger("code"), 800) &&
Objects.equals(json.getString("msg"), "msg")) {
jsonArray.remove(item);
}
}
log.info("jsonArray: {}", jsonArray);
}
2、哪些情况下会产生ConcurrentModificationException异常
- 通常在遍历集合的同时对其进行修改时抛出
- 如果在使用迭代器遍历集合时,集合结构发生了变化(例如添加或删除元素)
- 多个线程同时对同一个集合进行修改
3、如果避免ConcurrentModificationException异常
- 如果多个线程同时访问同一个集合,可以使用线程安全的集合类,如ConcurrentHashMap或CopyOnWriteArrayList
- 在使用迭代器遍历集合时,可以使用迭代器自身的remove方法来安全地删除元素,而不是使用集合类的remove方法
3.1、使用CopyOnWriteArrayList
@Test
public void ConcurrentModificationExceptionTest() {
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 800);
jsonObject.put("msg", "msg");
jsonArray.add(jsonObject);
CopyOnWriteArrayList<Object> writeArrayList = new CopyOnWriteArrayList<>(jsonArray);
for (Object item : writeArrayList) {
JSONObject json = JSON.parseObject(JSON.toJSONString(item));
if (Objects.equals(json.getInteger("code"), 800) &&
Objects.equals(json.getString("msg"), "msg")) {
writeArrayList.remove(item);
}
}
log.info("writeArrayList: {}", writeArrayList);
}
3.2、基于下标遍历
@Test
void ConcurrentModificationExceptionTest() {
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 800);
jsonObject.put("msg", "msg");
jsonArray.add(jsonObject);
for (int i = 0; i < jsonArray.size(); i++) {
Object item = jsonArray.get(i);
JSONObject json = JSON.parseObject(JSON.toJSONString(item));
if (Objects.equals(json.getInteger("code"), 800) &&
Objects.equals(json.getString("msg"), "msg")) {
jsonArray.remove(i);
}
}
log.info("jsonArray: {}", jsonArray);
}