我们先创建一个集合类,并在里面随机添加长度为8的字符串
可以发现数据是正常的打印出来
当我们开启多线程的时候,这里注意看变化。
这里可以看到,数据都乱了,当我们在开发项目时出现数据不一致是一件很致命的事情。
问题原因
多个线程在运行时,有的线程在写,有的线程在读。例如:线程A正在书写“ABC”时,线程B已经把数据读出来。
如果我们把线程增加至30个时,会出现异常java.util.ConcurrentModificationException
异常故障:java.util.ConcurrentModificationException
解决方案:
1、将ArrayList替换成Vector
List<String> list = new Vector<>();
2、使用Collections.synchronizedList(new ArrayList<>())
List<String> list = Collections.synchronizedListnew ArrayList<>());
3、使用CopyOnWriteArrayList()
List<String> list =new CopyOnWriteArrayList();
CopyOnWriteArrayList()的读写复制
先看源码
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
当我们调用add()方法的时候,会先复制一个数组Object[] elements给其他线程读取。
然后使用Arrays.copyOf()复制一个新的数组Object[] newElements,并且长度+1,采用newElements添加数据。
这时可以保证有的线程在写,有的线程在读时不会出错,这就是CopyOnWriteArrayList()的读写复制。