在一次代码中,遇到了Concurrentmodificationexception异常,使用场景如下,我在一个操作完成后,另一个线程会异步监听该操作完成事件,参考代码如下:
@Asynchronous
public void testEventReceiver(TestEvent TestEvent) {
getMessageFromDemo(TestEvent.getDemo());
}
随后操作获取到的demo对象进行遍历操作:
private void getMessageFromDemo(Demo demo) {
try {
demo.getMeesage().forEach(item -> message.update(item.getId(), "Unable"));
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage(), e);
}
}
结果出现了Concurrentmodificationexception 异常,这个异常产生的本因是操作Collection对象,进行循环遍历时,另一个线程修改了内部的值,更详细的可参考官方:
https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html 进行查阅,
先说明下原因主要是hibernate内部的lazy-load导致的,lazy-load的主要目的是为了减缓加载关联对象,在这里,获取到的demo对象是一个代理对象,并不是从数据库中获取到的,直到执行getMessage方法时,获取到的才是从数据库中拿到的,而在此时别的线程对数据库对象进行了修改,进而产生了Concurrentmodificationexception的异常
解决方法是通过Id首先从数据库中查询到对应的Demo对象,就不会有代理对象和实际对象不一致的情况了。
本文对出现的操作进行了记录,本人目前还处于学习阶段,欢迎各位提出想法与意见。