案例代码
1package com.atguigu.unit1.unit2;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.List;
6import java.util.UUID;
7
8public class ArrayListDemo {
9 public static void main(String[] args) {
10 final List<String> list = new ArrayList<String>();
11 for (int i = 0; i < 30; i++) {
12 new Thread(new Runnable() {
13 public void run() {
14 list.add(UUID.randomUUID().toString().substring(0, 8));
15 System.out.println(list.toString());
16 }
17 }).start();
18 }
19
20 }
21}
运行会出现java.util.ConcurrentModificationException
错误
出错原因
多个线程同时向列表中添加数据时,当前线程还没有添加成功,另一个线程突然抢占资源并添加元素,此时会出现并发读写不一致错误。
解决方案
Vector
1package com.atguigu.unit1.unit2;
2
3import java.util.*;
4
5public class ArrayListDemo {
6 public static void main(String[] args) {
7 // Vector是线程安全的
8 List<String> list = new Vector<String>();
9 for (int i = 0; i < 30; i++) {
10 new Thread(new Runnable() {
11 public void run() {
12 list.add(UUID.randomUUID().toString().substring(0, 8));
13 System.out.println(list.toString());
14 }
15 }).start();
16 }
17 }
18}
Collections工具类别
1package com.atguigu.unit1.unit2;
2
3import java.util.*;
4
5public class ArrayListDemo {
6 public static void main(String[] args) {
7 // 使用Collections工具类把ArrayList包装成线程安全的类
8 List<String> list = Collections.synchronizedList(new ArrayList<String>());
9 for (int i = 0; i < 30; i++) {
10 new Thread(new Runnable() {
11 public void run() {
12 list.add(UUID.randomUUID().toString().substring(0, 8));
13 System.out.println(list.toString());
14 }
15 }).start();
16 }
17 }
18}
CopyOnWriteArrayList
1package com.atguigu.unit1.unit2;
2
3import java.util.*;
4import java.util.concurrent.CopyOnWriteArrayList;
5
6public class ArrayListDemo {
7 public static void main(String[] args) {
8 final List<String> list = new CopyOnWriteArrayList<String>();
9 for (int i = 0; i < 30; i++) {
10 new Thread(new Runnable() {
11 public void run() {
12 list.add(UUID.randomUUID().toString().substring(0, 8));
13 System.out.println(list.toString());
14 }
15 }).start();
16 }
17 }
18}
CopyOnWriteArrayList源码
写时复制
CopyOnWrite容器即写实复制的的容器。往一个容器中添加元素的时候,不直接往当前容器Object[]添加,而是先将当前容器Object[]进行Copy,复制出一个新的容器Object[] newElements,然后新的容器Object[] newElements里面添加元素,添加完元素之后,再将原容器的引用指向新的容器setArray(newElements)。这样做的好处是可以对CopyOnWrite容器进行并发的读而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。
1public class CopyOnWriteArrayList implements List{
2 // 加了volatile进行同步
3 private transient volatile Object[] array;
4
5 public boolean add(E e) {
6 final ReentrantLock lock = this.lock;
7 lock.lock();
8 try {
9 Object[] elements = getArray();
10 int len = elements.length;
11 Object[] newElements = Arrays.copyOf(elements, len + 1);
12 newElements[len] = e;
13 setArray(newElements);
14 return true;
15 } finally {
16 lock.unlock();
17 }
18 }
19}