Java CopyOnWriteArrayList引发CurrentModificationException

Java CopyOnWriteArrayList引发CurrentModificationException,java,multithreading,exception,collections,Java,Multithreading,Exception,Collections,当我迭代一个列表时,我偶尔会得到一个ConcurrentModificationException。谷歌搜索告诉我,这可能是因为我在另一个线程中在对列表进行迭代时更改了该列表,为了解决这个问题,我应该使用java.util.concurrent.CopyOnWriteArrayList 。。。但我已经是了 显然,我在某处做了一件非常愚蠢的事 有人知道如何诱导CopyOnWriteArrayList抛出ConcurrentModificationException?如果重要的话,我正在使用Java

当我迭代一个列表时,我偶尔会得到一个
ConcurrentModificationException
。谷歌搜索告诉我,这可能是因为我在另一个线程中在对列表进行迭代时更改了该列表,为了解决这个问题,我应该使用
java.util.concurrent.CopyOnWriteArrayList

。。。但我已经是了

显然,我在某处做了一件非常愚蠢的事

有人知道如何诱导
CopyOnWriteArrayList
抛出
ConcurrentModificationException
?如果重要的话,我正在使用Java5

编辑:由于我正在使用的变异子可能很重要,我将用两种方式修改此列表:

  • 在前面添加元素。(
    list.add(0,新元素);
  • 使用子列表让旧项目从背面脱落。(
    list=list.subList(0,最大列表大小);
那些会升起红旗吗?若然,原因为何?我的理解是,因为这些操作首先复制对象,所以任何现有迭代器都会指向未修改的原始对象,因此不会在意。我的知识有漏洞吗

编辑2:导致问题的确切代码仍然有点模糊,但我至少可以发布我看到的异常:

java.util.ConcurrentModificationException
    at java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(Unknown Source)
    at java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(Unknown Source)
    at....

java.util.ConcurrentModificationException
位于java.util.concurrent.CopyOnWriteArrayList$COWSubList.checkForComodification(未知源)
位于java.util.concurrent.CopyOnWriteArrayList$COWSubList.iterator(未知源)
在

。。。在我的代码中,它指向一个for-each循环实例化

COWSubList
似乎确实意味着我对
subList
的调用是我问题的根源;我还是想知道为什么

编辑3:*facepalm*

CopyOnWriteArrayList.subList()
返回一个
列表,而不是
CopyOnWriteArrayList
。它返回的列表没有提供COWAL任何保护的隐含义务。这使得像这样使用
subList()
删除元素是一个非常糟糕的主意


不知道这是否是我的罪魁祸首,但它非常可疑,无论如何都需要更正。

CopyOnWriteArrayList.SubList如果包含列表从下面更改,则会抛出ConcurrentModificationException:

public class ListTest {

  private static List<int[]> intList;

  public static void main (String[] args) {
    CopyOnWriteArrayList<Integer> cowal = new CopyOnWriteArrayList<Integer>();
    cowal.add(1);
    cowal.add(2);
    cowal.add(3);

    List<Integer> sub = cowal.subList(1, 2);
    cowal.add(4);
    sub.get(0); //throws ConcurrentModificationException
  }
}
公共类列表测试{
私有静态列表;
公共静态void main(字符串[]args){
CopyOnWriteArrayList cowal=新的CopyOnWriteArrayList();
增加第(1)款;
增加(2);
增加(3);
列表子列表=cowal.子列表(1,2);
增加(4);
sub.get(0);//抛出ConcurrentModificationException
}
}

Sbodd的答案是正确的,但听起来使用CopyOnWriteArrayList而不是ArrayList只是试图掩盖错误。真正的问题是在遍历基础列表时试图修改它。您需要在代码中找到访问它的位置,并删除该用法或解决它。

am确实在调用子列表,所以这可能就是它。(很难说,因为错误是在现场发生的,而不是在我的test rig.Grr上。)然而,为了让它更像我的代码,我将“cowal”改为一个简单的“List”,并且没有考虑中间的“sub”变量;我做了“cowal=cowal.subList(1,2);”。在这些情况下,代码运行时不会发生意外。subList()调用还有其他方法会引起麻烦吗?matt b:我会的,但是代码太多了,我还没有弄清楚如何将它剥离到抛出错误的地方。(然而。)如果我提出了一个简单的版本(而且答案不会跳起来打我的脸),我会发布它。仍然没有准确地在本地复制错误,但我90%确定subList()确实是我痛苦的根源。(请参阅编辑的问题了解详细原因。)感谢您为我指明了正确的方向。除了,在对基础列表进行迭代时修改它是否安全?CopyOnWriteArrayList存在的原因?这是一个老问题,但仍应注意
list=list.subList(0,最大列表大小)
是一种可怕的删除元素的方法,因为子列表仍然引用包含所有元素的原始列表,因此,这会造成内存泄漏。删除末尾元素的标准方法是
list.subList(MAX_list_SIZE,list.SIZE()).clear()通常情况下,子列表是用于将任意列表操作应用于列表的一部分的工具,因此它们应该仅在整个操作过程中暂时保留。