我无法弄清楚这个并发修改异常



我觉得我的Java生锈了,所以我尝试了一个简单的问题:一个只返回唯一值的链表的合并排序。下面是我的第一次尝试。这对我来说很有意义。问题是,无论我做什么,我总是得到一个ConcurrentModificationException

我尝试过的事情包括:

  • 制作模块或方法synchronized .
  • 用迭代器替换sort方法中的LinkedLists
  • 在单独的变量中跟踪列表的大小(该部分被留在)。

毫无效果。ConcurrentModificationsException移动到其他地方,但仍留在原地。我真的不知道为什么。我该如何解决这个问题?

在这个特殊的尝试中,异常发生在调用addAll时。我把列表上的所有操作都放在它们自己的块中,但Java显然不在乎。

package com.regularoddity.dotcloud;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Merge {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        List<Integer> myList = new LinkedList<Integer>();
        myList.add(2);
        myList.add(9);
        myList.add(1);
        myList.add(3);
        myList.add(8);
        myList.add(7);
        myList.add(1);
        myList = sort(myList);
        Iterator<Integer> lit = myList.iterator();
        while(lit.hasNext()) System.out.printf("%s ", lit.next());
    }
    private static List<Integer> merge(List<Integer> list1, List<Integer> list2) {
        List<Integer> result = new LinkedList<Integer>();
        int size1 = list1.size();
        int size2 = list2.size();
        {
            while (size1 > 0 && size2 > 0) {
                if (list1.get(0) == list2.get(0)) {
                    result.add(list1.remove(0));
                    list2.remove(0);
                    size1--; size2--;
                }
                else if (list1.get(0) <= list2.get(0))
                {
                    result.add(list1.remove(0));
                    size1--;
                }
                else
                {
                    result.add(list2.remove(0));
                    size2--;
                }
            }
        }
        result.addAll(list1);
        result.addAll(list2);
        return result;
    }
    private static List<Integer> sort(List<Integer> list) {
        int lsize = list.size();
        if (lsize <= 1) return list;
        int pivot = lsize / 2;
        List<Integer> list1 = list.subList(0, pivot);
        List<Integer> list2 = list.subList(pivot, lsize);
        list1 = sort(list1);
        list2 = sort(list2);
        return merge(list1, list2);
    }

}

最让我困惑的是,我从来没有显式地对列表进行交互。一定有一个隐含的迭代在进行,但我似乎无法将其分解出来。

编辑:我没有包括堆栈跟踪,因为我(愚蠢地)认为,因为它在每次尝试修复时都会改变,所以它不会有用。但是,实际上,它并没有改变多少。下面是当前实现的堆栈跟踪:

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.SubList.checkForComodification(AbstractList.java:752)
    at java.util.SubList.size(AbstractList.java:625)
    at com.regularoddity.dotcloud.Merge.merge(Merge.java:30)
    at com.regularoddity.dotcloud.Merge.sort(Merge.java:64)
    at com.regularoddity.dotcloud.Merge.sort(Merge.java:62)
    at com.regularoddity.dotcloud.Merge.main(Merge.java:23)

com.regularoddity.dotcloud.Merge.main (Merge.java: 23)

subList的javadoc状态:

如果后备列表(即此列表)以任何方式在结构上被修改,而不是通过返回的列表,则此方法返回的列表的语义将变得未定义。

在本例中,调用subList两次,并通过两个子列表修改原始列表。这就是你的异常的来源。

不需要修改太多的代码,你可以简单地复制来避免这个问题:

List<Integer> list1 = new LinkedList<> (list.subList(0, pivot));
List<Integer> list2 = new LinkedList<> (list.subList(pivot, lsize));

相关内容

  • 没有找到相关文章

最新更新