Java 对子列表调用size()时ConcurrentModificationException
我试图保存一堆SQL事务。我处于ESB路由的上下文中,从SQL源传输到SQL目标,并且SQL事务的顺序不能保证,因此可以在插入对象之前进行SQL更新 由于体系结构的原因,我将这些SQL事务保存1000乘1000(我使用的是messageQueue)。因此,其中一些可能会失败,我会重新路由它们,以便重试或拒绝它们。为了提高效率,我愿意改进较旧的系统,如果1000失败,则通过递归实现二分法(如果保存失败,则拆分列表并重试)。我也在跟踪我的对象的属性,这要感谢另一个列表(objectsNo),以便进行进一步的操作 然而,在调用objectsList.size()的第一个递归中,我得到了一个ConcurrentModificationException。我怎样才能避免呢?我也很开放,非常感谢任何能够提供二分法以外的另一种方法来提高效率的解决方案(这样就可以绕过我的问题) 抑制:java.util.ConcurrentModificationException:null 在java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231)中 位于java.util.ArrayList$SubList.size(ArrayList.java:1040) 位于fr.company.project.esbname.mariadb.MariaDbDatabase.saveObjectWithDichoomie(MariaDbDatabase.java:398) 位于fr.company.project.esbname.mariadb.MariaDbDatabase.saveobjectwithdichodicie(MariaDbDatabase.java:404) 位于fr.company.project.esbname.mariadb.MariaDbDatabase.saveObject(MariaDbDatabase.java:350) 位于sun.reflect.GeneratedMethodAccessor324.invoke(未知源) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)中 位于java.lang.reflect.Method.invoke(Method.java:498) 位于org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:472) 位于org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:291) 在org.apache.camel.component.bean.MethodInfo$1.procedure上(MethodInfo.java:264) 位于org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:178) 位于org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77) 位于org.apache.camel.processor.RedeliveryRorHandler.process(RedeliveryRorHandler.java:541) ... 省略22个公共帧 我试图理解,但不应该有任何错误。即使我使用递归,它仍然是单线程的。我认为问题可能出在hibernate上(保存失败的一些请求可能会留在缓存中,并锁定修改),但问题出在原始列表的子列表上的大小上Java 对子列表调用size()时ConcurrentModificationException,java,performance,hibernate,exception,Java,Performance,Hibernate,Exception,我试图保存一堆SQL事务。我处于ESB路由的上下文中,从SQL源传输到SQL目标,并且SQL事务的顺序不能保证,因此可以在插入对象之前进行SQL更新 由于体系结构的原因,我将这些SQL事务保存1000乘1000(我使用的是messageQueue)。因此,其中一些可能会失败,我会重新路由它们,以便重试或拒绝它们。为了提高效率,我愿意改进较旧的系统,如果1000失败,则通过递归实现二分法(如果保存失败,则拆分列表并重试)。我也在跟踪我的对象的属性,这要感谢另一个列表(objectsNo),以便进行
private List<String> saveObjectWithDichotomie(List<Object> objects,
List<String> objectsNo,
Exchange exchange) throws JsonProcessingException {
try {
objectRepository.save(objects);
return objectsNo;
} catch (DataIntegrityViolationException e) {
if (objects.size() == 1) {
objectsNo.clear();
errorProcessor.sendErrorToRejets(objects.get(0), exchange, e);
return objectsNo;
} else {
List<Object> objectsFirstHalf = objects.subList(0, objects.size()/2);
List<Object> objectsSecondHalf = objects.subList(objects.size()/2, objects.size());
List<String> objectsNoFirstHalf = objectsNo.subList(0, objectsNo.size()/2);
List<String> objectsNoSecondHalf = objectsNo.subList(objectsNo.size()/2, objectsNo.size());
objectsNo.clear();
objectsNo.addAll(
saveObjectWithDichotomie(objects, objectsNoFirstHalf, exchange)
);
objectsNo.addAll(
saveObjectWithDichotomie(objects, objectsNoSecondHalf, exchange)
);
return objectsNo;
}
}
}
private List saveobjectwithdichoomie(列表对象,
列表对象no,
Exchange)引发JsonProcessingException{
试一试{
objectRepository.save(对象);
返回对象sno;
}捕获(DataIntegrityViolationException e){
if(objects.size()==1){
objectsNo.clear();
errorProcessor.sendErrorToRejets(objects.get(0)、exchange、e);
返回对象sno;
}否则{
列表对象firsthalf=objects.subList(0,objects.size()/2);
List objectsSecondHalf=objects.subList(objects.size()/2,objects.size());
List objectsNoFirstHalf=objectsNo.subList(0,objectsNo.size()/2);
List objectsNoSecondHalf=objectsNo.subList(objectsNo.size()/2,objectsNo.size());
objectsNo.clear();
objectsNo.addAll(
使用二分法保存对象(对象、对象上半部分、交换)
);
objectsNo.addAll(
使用二分法保存对象(对象、对象二分之一、交换)
);
返回对象sno;
}
}
}
两件事:
ConcurrentModificationException
并不意味着该列表已被另一个线程修改,而是意味着某个线程正试图以预期状态访问该列表,但同时该列表已被更改子列表
不会创建实际的新列表,而是在原始列表上创建一个视图。这意味着您不能在不使检索到的子列表无效的情况下更改原始列表public class Sublist {
public static void main(String[] args) {
List<String> list = new ArrayList<>(
IntStream.range(0, 100).mapToObj(Integer::toString).collect(Collectors.toList()));
List<String> sublist = list.subList(10, 20);
// outputs "15"
System.out.println(sublist.get(5));
list.clear();
// throws ConcurrentModificationException
System.out.println(sublist.get(5));
}
}
公共类子列表{
公共静态void main(字符串[]args){
列表=新的ArrayList(
IntStream.range(01100).mapToObj(Integer::toString.collect(Collectors.toList());
列表子列表=列表。子列表(10,20);
//产出“15”
System.out.println(sublist.get(5));
list.clear();
//抛出ConcurrentModificationException
System.out.println(sublist.get(5));
}
}
如果您愿意阅读子列表的文档,它清楚地表明:
返回的列表由该列表支持,因此返回列表中的非结构性更改将反映在此列表中,反之亦然
这就是异常的原因(不需要多个线程)。因此,创建新列表时,请通过以下方式创建:
List<Object> objectsFirstHalf = new ArrayList<>(objects.subList(0, objects.size()/2));
List objectsFirstHalf=new ArrayList(objects.subList(0,objects.size()/2));
当您删除或添加某些内容时,您正在更改列表,这就是为什么您会得到例外情况您可能是对的,但我不明白为什么,我只是在列表上调用大小,然后创建一个子列表。我既没有删除也没有添加任何内容。我以前搜索过类似的问题,我看到了与你类似的答案,但我认为这与我的问题无关
List<Object> objectsFirstHalf = new ArrayList<>(objects.subList(0, objects.size()/2));