CopyOnWriteArrayList
大约 1 分钟JavaJUC并发编程
ArrayList并发修改异常
public class ListTest {
public static void main(String[] args) {
List<String> list = new ArrayList();
for (int i = 1; i <= 10; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0,5));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
程序报错(多运行几次,也有不报错的):
[74b29, 086cd, 944b4]
[74b29, 086cd, 944b4, 98fb1, c9918, 3068b]
[74b29, 086cd, 944b4, 98fb1, c9918, 3068b, 928f0, 5f0d6, 0dd3f]
[74b29, 086cd, 944b4, 98fb1, c9918]
[74b29, 086cd, 944b4, 98fb1]
[74b29, 086cd, 944b4]
[74b29, 086cd, 944b4, 98fb1, c9918, 3068b, 928f0, 5f0d6]
[74b29, 086cd, 944b4, 98fb1, c9918, 3068b, 928f0]
Exception in thread "3" Exception in thread "1" java.util.ConcurrentModificationException
java.util.ConcurrentModificationException 并发修改异常。
并发下,ArrayList是不安全的。
解决办法
1、使用线程安全集合Vector
List<String> list = new Vector<>();
[324d5, c50d1]
[324d5, c50d1, 7dcc0, 6381a, dfd0d, 9e06f, b9e1c, 26a1b, b95c0, 7b0fb]
[324d5, c50d1, 7dcc0, 6381a, dfd0d, 9e06f, b9e1c, 26a1b, b95c0]
[324d5, c50d1, 7dcc0, 6381a, dfd0d, 9e06f, b9e1c, 26a1b]
[324d5, c50d1, 7dcc0, 6381a, dfd0d, 9e06f, b9e1c]
[324d5, c50d1, 7dcc0, 6381a, dfd0d, 9e06f, b9e1c]
[324d5, c50d1, 7dcc0, 6381a, dfd0d, 9e06f]
[324d5, c50d1, 7dcc0, 6381a, dfd0d]
[324d5, c50d1, 7dcc0, 6381a]
[324d5, c50d1, 7dcc0]
Process finished with exit code 0
2、使用集合工具类Collections.synchronizedList
List<String> list = Collections.synchronizedList(new ArrayList<>());
3、JUC包下的CopyOnWriteArrayList类
List<String> list = new CopyOnWriteArrayList<>();

CopyOnWrite写入时复制
COW:计算机程序设计领域的一种优化策略。
多个线程调用的时候,读取的时候list是固定的。写入的时候可能会存在覆盖操作。在写入的时候,避免覆盖造成数据问题。
读写分离。
CopyOnWriteArrayList的优势
Vector直接在方法上使用synchronized加了锁,性能较低。

CopyOnWriteArrayList使用的是Lock锁。性能更好。
