CopyOnWriteArrayList是java.util.Concurrent包中的一个类。这是在Java 5中引入的,作为java并发API变化的一部分。它被用于多线程的安全应用程序。这是ArrayList的一个并发版本。
为什么引入CopyOnWriteArrayList?
ArrayList是java集合中的列表实现,ArrayList不是线程安全的,不能用于多线程应用。见下面的例子 创建ArrayList对象。使用Iterate方法对每个元素进行遍历。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ArrayListDemo {
public static void main(String args[]) {
List names = new ArrayList<>();
names.add("one");
names.add("two");
names.add("three");
names.add("four");
Iterator it = names.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(value);
if (value.equals("three")) {
names.remove("four");
names.add("five");
names.add("four");
}
}
System.out.println(names.size());
}
}
在迭代过程中,当一个元素在iterator()中被移除时,iterator.next()方法会抛出ConcurrentModifiedException:
one
two
three
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at ArrayListDemo.main(ArrayListDemo.java:14)
ArrayList是快速失败的,这意味着如果列表被添加或删除,如果任何线程正在进行迭代,Next()方法会抛出ConcurrentModifiedException ArrayList在多线程的应用程序中不会像预期那样工作。
CopyOnWriteArrayList对象如何工作?
多线程应用程序中的CopyOnWriteArrayList是一个与应用程序中的ArrayList相同或相似的类,当第一次对该列表调用iterator()时,它会创建一个列表的快照副本。它将为每一个修改(添加,设置删除)操作创建一个克隆版的数组列表,并且同步将由JVM完成。从性能上讲,它为每一个修改操作创建重复的拷贝,因此成本很高。
例子
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ListDemo {
public static void main(String args[]) {
List myList = new CopyOnWriteArrayList();
myList.add("ten");
myList.add("nine");
myList.add("eight");
myList.add("seven");
myList.add("six");
Iterator it = myList.iterator();
while (it.hasNext()) {
String element = it.next();
System.out.println(element);
if (element.equals("eight")) {
myList.remove("seven");
myList.add("five");
myList.add("four");
}
}
System.out.println(myList.size());
}
}
优点
- 当列表被其他线程修改/更新时,可以安全地迭代列表。
- 它最适合于读操作
- 适用于少数修改和许多读操作
缺点
如果你经常添加元素,这将是昂贵的:
- 在迭代过程中使用同步块来锁定
- 使用CopyOnWriteArrayList来避免这种异常。