代码之家  ›  专栏  ›  技术社区  ›  BlairHippo

CopyOnWriteArrayList引发CurrentModificationException

  •  14
  • BlairHippo  · 技术社区  · 16 年前

    我偶尔会得到 ConcurrentModificationException 当我遍历一个列表时。一个谷歌搜索告诉我,这可能是因为我正在修改另一个线程中的列表,同时在它上面迭代,为了使这个问题消失,我应该使用 java.util.concurrent.CopyOnWriteArrayList

    …但我已经是了。

    显然,我在做什么 真的? 愚蠢的地方。

    有人知道如何诱导 CopyOnWriteArrayList 投掷 当前修改例外 ?如果它很重要,我用的是Java 5。

    编辑: 因为我正在使用的突变可能很重要,所以我用两种方式修改这个列表:

    • 在前面添加元素。( list.add(0, newElement); )
    • 使用子列表让旧项目从后面脱落。( list = list.subList(0, MAX_LIST_SIZE); )

    那些会升起红旗吗?如果是,为什么?我的理解是,因为这些操作首先复制了该对象,所以任何现有的迭代器都将指向未修改的原始对象,因此不会在意。我的知识有漏洞吗?

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

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

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

    那个 COWSubList 似乎意味着我的电话 subList 是我问题的根源,我还是想知道为什么。

    编辑3: *FACEPALM *

    CopyOnWriteArrayList.subList() 返回A List , CopyOnWriteArrayList . 它返回的列表没有任何暗示的义务提供任何考尔的保护。这使得使用 subList() 像这样去掉元素是个很坏的主意。

    不知道这是不是我的罪魁祸首,但这是他妈的可疑,无论如何都需要纠正。

    2 回复  |  直到 16 年前
        1
  •  16
  •   Sbodd    16 年前

    CopyOnWriteArrayList.Sublists如果包含列表从下面更改,则抛出ConcurrentModificationExceptions:

    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
      }
    }
    
        2
  •  -1
  •   matt b    16 年前

    sbodd有正确的答案,但听起来使用copyonwritearraylist而不是arraylist只是试图掩盖错误。真正的问题是试图在遍历基础列表时对其进行修改。你需要在你的代码中找到你访问它的位置,然后删除这个用法或者解决它。

    推荐文章