java - 在子列表上调用 size() 时出现 ConcurrentModificationException

标签 java performance hibernate exception

我正在尝试保存一堆 SQL 事务。我在 ESB 路由的上下文中,从 SQL 源传输到 SQL 目标,SQL 事务的顺序无法保证,因此您可以在插入对象之前进行 SQL 更新。

由于架构原因,我将这些 SQL 事务 1000 x 1000 保存(我正在使用 messageQueue)。所以其中一些可能会失败,我重新路由它们以便重试或拒绝它们。为了提高效率,我愿意改进旧系统,如果1000失败,你1个保存,实现dichotomia(如果保存失败,你拆分列表重试) ,通过递归。多亏了另一个列表 (objectsNo) 的进一步操作,我还在跟踪我的对象的一个​​属性。

但是,在第一次递归调用 objectsList.size() 时,我得到了一个 ConcurrentModificationException。我怎样才能避免呢?我也很开放,非常感谢任何能够提供除二分法之外的另一种方式来提高效率(并且可以绕过我的问题)的解决方案。

Suppressed: java.util.ConcurrentModificationException: null at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231) at java.util.ArrayList$SubList.size(ArrayList.java:1040) at fr.company.project.esbname.mariadb.MariaDbDatabase.saveObjectWithDichotomie(MariaDbDatabase.java:398) at fr.company.project.esbname.mariadb.MariaDbDatabase.saveObjectWithDichotomie(MariaDbDatabase.java:404) at fr.company.project.esbname.mariadb.MariaDbDatabase.saveObject(MariaDbDatabase.java:350) at sun.reflect.GeneratedMethodAccessor324.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:472) at org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:291) at org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:264) at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:178) at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77) at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541) ... 22 common frames omitted

我试着理解了,应该不会有错。即使我使用递归,它仍然是单线程的。我认为问题可能与 hibernate 有关(一些失败的保存请求可能会保留在缓存中,并进行锁修改),但问题与大小有关,它位于原始列表的子列表中。

    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;
        }
    }
}

最佳答案

如果你会阅读 sublist 的文档,则清楚地说:

The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.

这就是你的异常的原因(不需要多线程就可以发生)。因此,当您创建一个新列表时,请通过以下方式创建它:

List<Object> objectsFirstHalf = new ArrayList<>(objects.subList(0, objects.size()/2));

关于java - 在子列表上调用 size() 时出现 ConcurrentModificationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51019828/

相关文章:

java - 为什么静态 hashmap 在下面的情况下总是 null

java - 小程序仅在我的设备上无法正常工作,程序没有错误

java - Hibernate @Audited 与 @Version 冲突

Java 9 javapacker 在创建 bss 时找不到 jfxrt.jar。在 Linux 下似乎在 "createbss"模式下完全损坏。如何避免错误?

java - 使用 Spring Boot 和 Thymeleaf 时出现 "Circular view path would dispatch back to the current handler URL."

c# 在所有文件中最快的字符串搜索

java - 如何使这段代码在 O(c.size()+n-i) 时间内运行?

c++ - 结构作为函数的参数 : more efficient to copy or dereference?

java - 使用 hibernate 保留基类和子类

java - 自动填充集