java - CopyOnWriteArrayList(cowal)

标签 java java.util.concurrent

我从一些教程中理解了这个概念,只要我知道一个线程何时迭代列表,就允许其他线程修改底层列表,我们不会得到 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);
}

最佳答案

您将收到 ConcurrentModificationException,因为 ArrayList 的迭代器在设计上是快速失败。这意味着,一旦创建了迭代器,如果ArrayList修改(添加或删除元素),它将抛出ConcurrentModificationException

如果您检查异常日志语句,它会被 itr.next() 方法在 String s=itr.next(); 行抛出,因为 迭代器的 next() 方法通过使用其复制的 modCount 变量调用 checkForCommodification() 方法检查 ArrayList 大小的修改情况从列表创建迭代器时。

现在让我们谈谈 CopyOnWriteArrayList,您没有收到此异常的原因是 CopyOnWriteArrayList线程安全变体 ArrayList,其中所有可变操作(如添加、删除、设置)都是通过将内部数组复制到新数组并用新创建的数组替换旧数组来实现的。

因此,当您从列表中获取迭代器时,它会保存数组的引用,并且当您向列表添加元素时,列表将拥有全新的数组。并且迭代器仍然指向旧数组。

您可能已经注意到,通过语句 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]

希望这有帮助。 享受吧:)

关于java - CopyOnWriteArrayList(cowal),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47862954/

相关文章:

dictionary - ConcurrentHashMap如何获取tailMap?

java - 为什么 CopyOnWriteArrayList 与迭代不可修改列表不同?

java - 动态更改 ThreadPoolExecutor 的 corePoolSize

java - java.util.concurrent.LinkedBlockingQueue 中的奇怪代码

java - 不合规 JVM 不发送 WindowClosing 事件的解决方法

java - JComboBox 在单击之前不显示

java - 每天使用 Camel 从 FTP 服务器读取带日期戳的文件

java - extras.getString() 检索正​​确的值但分配 null

java - 如果我没有与我关联的域,我应该如何命名包?

Java ConcurrentSkipListSet 与文档不一致