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

Bor*_*eld 4 java performance hibernate exception

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

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

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

已抑制:java.util.ConcurrentModificationException:在 fr.company.project 的 java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231) 处为 null,在 java.util.ArrayList$SubList.size(ArrayList.java:1040) 处为 null。 esbname.mariadb.MariaDbDatabase.saveObjectWithDichotomie(MariaDbDatabase.java:398) 在 fr.company.project.esbname.mariadb.MariaDbDatabase.saveObjectWithDichotomie(MariaDbDatabase.java:404) 在 fr.company.project.esbname.mariadb.MariaDbDatabase.saveObject( MariaDbDatabase.java:350) 在 sun.reflect.GenerateMethodAccessor324.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.proceed(MethodInfo.java:264) 在 org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:178) 在 org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor .java:77) at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:541) ... 省略了 22 个常见帧

我试着去理解,但应该不会有什么错误。即使我使用递归,它仍然是单线程的。我认为问题可能出在休眠(来自失败的保存的一些请求可能保留在缓存中,并锁定修改),但问题在于大小,它位于原始列表的子列表上。

    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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Eug*_*ene 5

如果您阅读文档,sublist则明确表示:

返回的列表受此列表支持,因此返回列表中的非结构性更改会反映在此列表中,反之亦然。

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

List<Object> objectsFirstHalf = new ArrayList<>(objects.subList(0, objects.size()/2));
Run Code Online (Sandbox Code Playgroud)