代码之家  ›  专栏  ›  技术社区  ›  Ruchir Chauhan

CopyOnWriteArrayList(cowal)

  •  0
  • Ruchir Chauhan  · 技术社区  · 7 年前

    我从一些教程中理解了这个概念,只要我知道当一个线程迭代列表时,另一个线程就可以修改底层列表,我们不会得到ConcurrentModificationException(CME),但在ArrayList的情况下,我们会得到CME。

    但是在下面的程序中,只有一个线程(主线程),但我仍然得到了CME。。为什么?

    是因为迭代器吗?

    如果我用COWAL替换AL,我没有任何例外,但我也没有元素“D”。。为什么?

    AL<String> l=new AL<>();
    l.add("a");
    l.add("b");
    l.add("c");
    Iterator<String> itr=l.iterator();
    l.add("d");
    while(itr.hasNext())
    {
     String s=itr.next();
    Sop(s);
    }
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   Neetesh Bhardwaj    7 年前

    您正在 ConcurrentModificationException 因为 ArrayList 的迭代器为 快速故障 按设计。这意味着一旦创建了迭代器 阵列列表 修改(添加或删除元素) ,它将抛出 ConcurrentModificationException .

    如果您检查exception log语句,它将在第行抛出 String s=itr.next(); 通过 itr.next() 方法,因为 next() 迭代器的方法通过调用 checkForComodification() 尺寸方法 阵列列表 使用 modCount 从列表创建迭代器时复制的变量。

    现在让我们谈谈 CopyOnWriteArrayList 您没有得到此异常的原因是 CopyOnWriteArrayList 是一个 线程安全变量 属于 阵列列表 在这种方法中,通过将内部数组复制到新数组并用新创建的数组替换旧数组,可以实现添加、删除、设置等所有可变操作。

    所以,当您从列表中获取迭代器时,它会保存一个数组引用,当您向列表中添加一个元素时,列表中会有一个全新的数组。迭代器仍然指向旧数组。

    您可能已经注意到,新添加的element by语句 l.add("d"); 控制台上未打印。但如果你打印出整个列表,它就在那里。

    这是您的示例代码 CopyOnWriteArrayList :

        List<String> l = new CopyOnWriteArrayList<>();
        l.add("a");
        l.add("b");
        l.add("c");
        Iterator<String> itr = l.iterator();
        l.add("d");
        while (itr.hasNext()) {
            String s = itr.next();
            System.out.println(s);
        }
        System.out.println(l);
    

    输出为生产为:

    a
    b
    c
    [a, b, c, d]
    

    希望这有帮助。 享受:)

        2
  •  1
  •   DhaRmvEEr siNgh    7 年前

    错误是因为行

    l.add("d");
    

    在创建迭代器之后,您正在修改列表结构(添加或删除元素)。

    当你打电话时

    itr.next();
    

    它在内部检查列表中的任何结构更改(在ArrayList中添加或删除),发现添加了一个元素,因此数组列表的大小发生了变化。。这就是为什么你会得到这个例外。

    如果在创建迭代器之前或使用迭代器之后添加该元素,则不会出现此错误。。

    下面是ArrayList类中next()的代码;

         @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
           ......
            return (E) elementData[lastRet = i];
        }
    
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }