为什么即使我没有编辑任何内容也会收到 ConcurrentModificationException?

Why do I get a ConcurrentModificationException even though I do not edit anything?

我正在尝试将一些串行代码转换为一些 'nice' 多线程代码,但是当我尝试 运行 它时,我得到了迭代器的 java.util.ConcurrentModificationException在我正在迭代的 Set 中获取超过 200 个元素。我认为只有当您尝试修改您正在尝试 acces/iterate 或反之亦然的内容时,您才会得到此异常,但我没有更改任何内容。

我正在谈论的示例迭代 TreeMapkeySet,代码如下所示:

private static SortedMap<BigInteger,Long> algorithm7(int n, 
        final SortedMap<BigInteger, Long> S, ExecutorService pool) {

    final SortedMap<BigInteger,Long> S1 = new TreeMap<BigInteger, Long>();
    final SmallAntiChain alfa = SmallAntiChain.universeAntiChain(n);
    final SmallAntiChain u = SmallAntiChain.universeAntiChain(n+1);
    final SmallAntiChain l = SmallAntiChain.singletonAntiChain(n+1);

    Future<?>[] list = new Future[S.size()];
    int i = 0;
    for (final BigInteger tCode : S.keySet()) {
        list[i++] = pool.submit(new Runnable() {

            @Override
            public void run() {
                SmallAntiChain t = SmallAntiChain.decode(tCode);
                Set<int[]> rtsymm = (t.join(l)).symmetryGroup();
                SortedMap<BigInteger, Long> St = new TreeMap<BigInteger, Long>();
                for (SmallAntiChain x : new AntiChainInterval(t.join(l),u.omicron(t, alfa))) {
                    BigInteger b = x.standard(rtsymm).encode(); 
                    Storage.store(St, b);
                }
                for (BigInteger b : St.keySet()) {
                    SmallAntiChain x = SmallAntiChain.decode(b);
                    BigInteger code = x.standard().encode();
                    Storage.store(S1,code,St.get(b)*S.get(tCode));
                }
            }

        });
    }

    try {
        for(Future<?> f : list)
            f.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }

    return S1;
}

调用方法如下所示:

public static SortedMap<BigInteger, Long>[] equivalenceClasses(int till, ExecutorService... pools) throws SyntaxErrorException {
    if(pools.length < 1)
        pools = new ExecutorService[]{ Executors.newFixedThreadPool(1) };
    @SuppressWarnings("unchecked")
    SortedMap<BigInteger, Long>[] reS = new TreeMap[till+1];
    reS[0] = new TreeMap<BigInteger,Long>();
    Storage.store(reS[0],SmallAntiChain.emptyAntiChain().standard().encode());
    Storage.store(reS[0],SmallAntiChain.emptySetAntiChain().standard().encode());
    int n = 0;
    while (n < till) {
        reS[n+1] = algorithm7(n,reS[n], pools[0]);
        n++;
    }
    return reS;
}

谁能告诉我为什么我得到异常以及我可以做些什么来解决这个问题?最好不必使用 ConcurrentSkipListMap 或不必更改签名中的任何内容。

提前致谢


编辑:完成代码并添加调用方法

根据 Java 规范,如果 SortedMap 未被 结构化 get(..) 不应抛出 ConcurrentModificationException修改的。由于您没有提供完整的代码,我唯一可以建议的是在创建 SortedMap 之后用 Collections.unmodifiableSortedMap(S s) 包装它。如果您错过了在结构上修改地图的代码,这将抛出一个 Exception

即使您提供的代码没有修改 SortedMap,也不排除外部(方法外)线程没有修改它。