CopyOnWriteArrayList(cowal)

CopyOnWriteArrayList(cowal)

问题描述:

我从一些教程中了解了这个概念,并且只要我知道一个线程正在迭代列表时,允许其他线程修改底层列表,并且我们不会得到ConcurrentModificationException(CME),但是在ArrayList的情况下,我们将获得CME。CopyOnWriteArrayList(cowal)

但在下面的程序中只有一个线程(主线程),但仍然获得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); 
} 
+0

我已经做了...“并发收集” –

+0

如果您将鼠标悬停在它上面,则说明这是.Net概念,而不是JVM。你得到这个异常的原因是因为在你已经获得一个迭代器之后你正在改变这个集合(AL) - 这里涉及到多少个线程并不重要。 – StuartLC

+0

我改变了标签..didnt通知,因为它显示.net的概念.. –

错误是因为线

l.add("d"); 

要修改表结构(添加或删除元素)迭代器创建后。

当您呼叫

itr.next(); 

内部,它是检查在列表中(添加在ArrayList的或去除)的任何结构改变和它创立存在一个元素添加,因此数组列表的大小已经改变..这就是为什么你得到这个例外。

如果你创建的Iterator的前或使用后,迭代器你不会得到这个错误添加元素..

下面

是的代码下一个()的ArrayList类;

 @SuppressWarnings("unchecked") 
    public E next() { 
     checkForComodification(); 
     ...... 
     return (E) elementData[lastRet = i]; 
    } 

    final void checkForComodification() { 
     if (modCount != expectedModCount) 
      throw new ConcurrentModificationException(); 
    } 

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

如果检查异常日志声明,它是在线路String s=itr.next();通过itr.next()方法,因为通过使用modCount变量,它的副本,同时创造从列表迭代器调用的ArrayList大小的checkForComodification()方法迭代器检查修饰next()方法抛出。

现在让我们说说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] 

希望这有助于。 享受:)