【发布时间】:2018-05-18 08:37:13
【问题描述】:
下面的方法抛出ConcurrentModificationException可能是什么原因?
static Set<String> setOfAllocAccountsIn(final @NotNull Execution execution) {
final Set<String> allocAccounts = new HashSet<>();
execution.legs().forEach(leg -> leg.allocs().forEach(alloc -> {
if (alloc.account() != null) {
allocAccounts.add(alloc.account());
}
}));
return allocAccounts;
}
堆栈跟踪:
"java.util.ConcurrentModificationException:
at java.base/java.util.ArrayList.forEach(ArrayList.java:1382)
at com.client.stp.util.DealsBuilderUtil.setOfAllocAccountsIn(DealsBuilderUtil.java:146)
at com.client.stp.builder.GridDealsObjectBuilder.build(GridDealsObjectBuilder.java:47)
at com.client.stp.processor.DealToPDXMLTransformer.transform(DealToPDXMLTransformer.java:29)
at com.client.stp.processor.WorkPartitionerEngine.lambda$onEventSubmit$0(WorkPartitionerEngine.java:40)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:514)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.base/java.lang.Thread.run(Thread.java:844)
使用简单的for-loop 可以正常工作。该方法由具有自己的执行对象副本的多个线程调用。
使用简单 for 循环的解决方案:
static Set<String> setOfAllocAccountsIn(final @NotNull Execution execution) {
final Set<String> allocAccounts = new HashSet<>();
for (final ExecutionLeg executionLeg : execution.legs()) {
for (final ExecutionAlloc executionAlloc : executionLeg.allocs()) {
if (executionAlloc.account() != null) {
allocAccounts.add(executionAlloc.account());
}
}
}
return allocAccounts;
}
我觉得它与静态方法及其由多个线程访问的局部变量有关,但根据理论,这将是线程局部变量并且不共享。给我一些时间来写一些简单的例子。
【问题讨论】:
-
堆栈跟踪说明了什么。
-
什么是
legs、allocs等等? -
@Ben...让我用简单的例子来更新一下。
-
如何创建
Execution对象的副本? -
请发帖minimal reproducible example。是否有可能其中一种方法修改了所涉及的集合之一(例如,
executionAlloc.account()修改了集合?)