Java CopyOnWriteArrayList类使用教程

x33g5p2x  于2021-08-22 转载在 Java  
字(3.1k)|赞(0)|评价(0)|浏览(141)

CopyOnWriteArrayList类概述

在这篇文章中,我们将讨论来自java.util.concurrent包的CopyOnWriteArrayList

这是一个在多线程程序中非常有用的结构--当我们想以线程安全的方式迭代一个列表而不需要明确的同步。
ArrayList的线程安全变体,其中所有的变异操作(添加、设置等)都是通过对底层数组进行新的复制来实现的。 

通常情况下,CopyOnWriteArrayList是非常昂贵的,因为它涉及到每次写操作的昂贵的数组拷贝,但是如果你有一个迭代次数超过变异次数的List,那么它就非常有效,例如,你主要需要迭代ArrayList,而不需要经常修改它。

我们将学到什么?

  1. CopyOnWriteArrayList类构造函数的总结
  2. 总结CopyOnWriteArrayList类方法 类的方法
  3. CopyOnWriteArrayList类的例子

1. CopyOnWriteArrayList类构造函数的总结

  • CopyOnWriteArrayList() - 创建一个空列表。
  • CopyOnWriteArrayList(Collection<? extends E> c) - 创建一个包含指定集合元素的列表,其顺序是由集合的迭代器返回。
  • CopyOnWriteArrayList(E[] toCopyIn) - 创建一个包含给定数组副本的列表。

2. CopyOnWriteArrayList类方法的总结

在类的下面,图中显示了CopyOnWriteArrayList类方法的列表。 

阅读更多关于CopyOnWriteArrayList类方法的内容 CopyOnWriteArrayList Javadoc 8.

3. CopyOnWriteArrayList类的例子

ConcurrentModificationException实例

我们知道CopyOnWriteArrayList的迭代器是fail-safe,不会抛出ConcurrentModificationException。让我们通过例子来证明这一点。 

首先让我们用一个例子来证明ArrayList的迭代器是fail-fast并且抛出ConcurrentModificationException

public class CopyOnWriteArrayListExample {

        private static List<Integer> list = new ArrayList<>();
        public static void main(final String[] args) {
           list.add(1);
           list.add(2);
           list.add(3);
  
           final Runnable runnable = () -> {
               list.add(4);
               list.add(5);
           };
  
          final Thread thread = new Thread(runnable);
          thread.start();
  
          final Iterator<Integer> iterator = list.iterator();
          while (iterator.hasNext()) {
              final Integer integer = iterator.next();
              System.out.println(integer);
          }
      }
}

输出。

1
Exception in thread "main" java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
 at java.util.ArrayList$Itr.next(ArrayList.java:859)
 at com.javaguides.collections.specialpurposeimpl.CopyOnWriteArrayListExample
.main(CopyOnWriteArrayListExample.java:33)

注意,在上面的例子中,我们是通过创建一个独立的线程来修改ArrayList的。
现在,让我们用CopyOnWriteArrayList类替换ArrayList,看看输出结果。 

下面是源代码。

//*/*
/*
/* This program demonstrates how CopyOnWriteArrayList works.
/*
/* @author www.javaguides.net
/*/

public class CopyOnWriteArrayListExample {

         private static List<Integer> list = new CopyOnWriteArrayList<>();
         publicstaticvoidmain(finalString[] args) {<<$2$>>
}

输出。

1
2
3
4
5

注意,CopyOnWriteArrayList的迭代器是安全的,不会抛出ConcurrentModificationException

不允许在迭代时删除

创建CopyOnWriteArrayList是为了允许在底层列表被修改时也能安全地迭代元素。

由于复制机制,不允许对返回的Iterator进行remove()操作--结果是UnsupportedOperationException

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

//*/*
/*
/* This program demonstrates how CopyOnWriteArrayList works.
/*
/* @author www.javaguides.net
/*/

public class CopyOnWriteArrayListExample {

      private static List<Integer> list = new CopyOnWriteArrayList<>();
      public static void main(final String[] args) {
          list.add(1);
          list.add(2);
          list.add(3);
  
          final Iterator<Integer> iterator = list.iterator();
          while (iterator.hasNext()) {
               final Integer integer = iterator.next();
               iterator.remove();
               System.out.println(integer);
          }
      }
}

输出。

Exception in thread "main" java.lang.UnsupportedOperationException
 at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1178)
 at com.javaguides.collections.specialpurposeimpl.CopyOnWriteArrayListExample.
main(CopyOnWriteArrayListExample.java:25)

###参考文献

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

相关文章