concurrentModificationException 是 Java 中常见的异常,通常发生在多个线程同时修改一个集合对象时。虽然你提到的是对复杂对象进行 toJsonString 或 parseObject 操作,但这个异常的根本原因可能与这些操作中涉及的集合对象有关。
可能的原因
多线程并发修改集合:
如果你的复杂对象中包含集合(如 List、Map、Set 等),并且多个线程同时修改这些集合(例如添加、删除元素),就可能会抛出 ConcurrentModificationException。
即使你只是在做 toJsonString 或 parseObject 操作,如果这些操作内部遍历了集合,而其他线程同时修改了集合,也会触发此异常。
非线程安全的集合:
Java 中的大多数集合类(如 ArrayList、HashMap)是非线程安全的。如果多个线程同时操作这些集合,可能会导致数据不一致或抛出异常。
JSON 库的内部实现:
某些 JSON 库(如 Gson 或 Fastjson)在序列化或反序列化时,可能会遍历对象的字段或集合。如果对象在遍历过程中被其他线程修改,就会抛出 ConcurrentModificationException。
解决方法
使用线程安全的集合:
将非线程安全的集合替换为线程安全的版本,例如:
ArrayList → CopyOnWriteArrayList
HashMap → ConcurrentHashMap
HashSet → ConcurrentHashSet
这样可以避免多线程并发修改时抛出异常。
加锁(同步):
在操作复杂对象时,使用 synchronized 关键字或 ReentrantLock 对代码块加锁,确保同一时间只有一个线程可以修改对象。
例如:
java
复制
synchronized (complexObject) {
String jsonString = toJsonString(complexObject);
// 其他操作
}
深拷贝对象:
在多线程环境中,可以先对复杂对象进行深拷贝,然后在副本上进行 toJsonString 或 parseObject 操作。这样可以避免原对象被并发修改。
例如:
java
复制
ComplexObject copy = deepCopy(complexObject);
String jsonString = toJsonString(copy);
使用不可变对象:
如果可能,将复杂对象设计为不可变对象(Immutable Object)。这样在多线程环境中,对象不会被修改,也就不需要担心并发问题。
检查 JSON 库的实现:
确保使用的 JSON 库是线程安全的。某些 JSON 库可能在内部使用了非线程安全的集合或缓存,导致并发问题。可以查阅相关文档或源码确认。
示例代码
以下是一个使用 ConcurrentHashMap 的示例,避免 ConcurrentModificationException:
java
复制
import java.util.concurrent.ConcurrentHashMap;
public class Example {
private ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
public void addData(String key, String value) {
map.put(key, value);
}
public String toJsonString() {
// 使用线程安全的集合,避免并发修改异常
return map.toString(); // 这里只是一个简单示例,实际可以使用 JSON 库
}
public static void main(String[] args) {
Example example = new Example();
// 模拟多线程操作
Thread t1 = new Thread(() -> {
for (int i = 0; i < 100; i++) {
example.addData("key" + i, "value" + i);
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 100; i++) {
example.addData("key" + i, "value" + i);
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(example.toJsonString());
}
}