我们一般情况下使用集合,都是在单线程的情况下,但是如果是多线程呢?会出现什么样的结果呢?
下面的代码,在多线程的情况下输出报出异常
Exception in thread “6” java.util.ConcurrentModificationException
原因在于并发情况下,多个线程会争抢资源,以至于导致数据修改不一致的情况引发并发修改异常。
举个例子:
就是我们过一个只能一个人通过的小道的时候,如果很多人素质不好,那么就有可能发生,一个人正在过着小道,其他人也争着抢着过,最后导致都过不了。
解决方法
- 1.使用Vector集合代替,不过这个一般不考虑,主要是因为太慢了
- 2.使用Collections.synchronized
- 3.使用JUC包下的CopyOnWriteArrayList
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 222; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(1,7));
System.out.println(list);
if(!list.isEmpty())
list.removeAll(list);
},String.valueOf(i)).start();
}
Exception in thread "6" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at java.util.AbstractCollection.toString(AbstractCollection.java:461)
at java.lang.String.valueOf(String.java:2994)
at java.io.PrintStream.println(PrintStream.java:821)
at ContainerNoSafeDemo.lambda$main$0(ContainerNoSafeDemo.java:12)
at java.lang.Thread.run(Thread.java:748)
使用Collections.synchronized代码
ArrayList<String> list = new ArrayList<>();
List<String> list1 = Collections.synchronizedList(list);
for (int i = 0; i < 222; i++) {
new Thread(()->{
list1.add(UUID.randomUUID().toString().substring(1,7));
System.out.println(list1);
if(!list1.isEmpty())
list1.removeAll(list1);
},String.valueOf(i)).start();
}
有多种方法可以选择根据你使用的集合类型
使用CopyOnWriteArrayList代码
CopyOnWriteArrayList list1 = new CopyOnWriteArrayList();
for (int i = 0; i < 222; i++) {
new Thread(()->{
list1.add(UUID.randomUUID().toString().substring(1,7));
System.out.println(list1);
if(!list1.isEmpty())
list1.removeAll(list1);
},String.valueOf(i)).start();
}
如果使用set可以选择CopyOnWriteArraySet
解读CopyOnWrite
CopyOnWrite容器是写时复制的容器,当向容器中添加元素时,不会直接往当前容器中添加,而是将当前容器进行copy 复制一个容器,然后往复制的容器添加元素,添加完成将复制的容器的引用指向新的容器(setArray(newElements)) 其实就是是用了读写分离的思想,读和写使用不同的容器
加源码
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();
}
}