ConcurrentModificationException异常
ArrayList集合是不安全的,将list集合的add操作放到线程中,结果报ConcurrentModificationException异常(并发修改异常)
public class ListTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
for (int i = 1; i <=10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,6));
System.out.println(list);
},String.valueOf(i)).start();
}
}
}
[436b52, 74be44, 9a6f28, 573ffb]
[436b52, 74be44, 9a6f28, 573ffb, fecd9b, 996b0f, 48ea29]
[436b52, 74be44, 9a6f28, 573ffb, fecd9b, 996b0f, 48ea29, 55e242]
[436b52, 74be44, 9a6f28, 573ffb, fecd9b, 996b0f]
[436b52, 74be44, 9a6f28, 573ffb, fecd9b]
[436b52, 74be44, 9a6f28, 573ffb, fecd9b, 996b0f, 48ea29, 55e242, b98eb6, d8d63d]
[436b52, 74be44, 9a6f28, 573ffb, fecd9b, 996b0f, 48ea29, 55e242, b98eb6]
Exception in thread "2" Exception in thread "3" Exception in thread "1" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911)
at java.util.ArrayList$Itr.next(ArrayList.java:861)
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 com.lfl.juc.collection.ListTest.lambda$main$0(ListTest.java:30)
at java.lang.Thread.run(Thread.java:748)
解决方案一
将ArrayList换成Vector
List<String> list = new Vector<String>();
解决方案二
使用Collections提供的方法,将ArrayList转为安全的
List<String> list = Collections.synchronizedList(new ArrayList<>());
解决方案三
使用JUC中的CopyOnWriteArrayList
List<String> list = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList底层
//创建一个空列表
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
setArray方法
//创建了一个数组
final void setArray(Object[] a) {
array = a;
}
数组由volatile修饰
private transient volatile Object[] array;
CopyOnWriteArrayList的add方法,其中用到了写入时复制的策略,另外,加锁的方式与Vector不同,Vector使用的是Synchronized关键字,而CopyOnWriteArrayList使用的是lock锁,所以CopyOnWriteArrayList的性能要好于Vector
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();
}
}