问题和解决方法
描述:1:我们在在多线程情况下用ArrayList a=new ArrayList();在add(param)添加信息常遇到ConcurrentModificationException
即并发修改异常
原因:多个线程争抢修改信息时候,当一个线程正在修改却被其他线程抢占去同一个位置的修改权造成修改错误,丢数据
代码--问题复现
public class UnSafeArrayList {
public static void main(String[] args){
List<String> list = new ArrayList<>();
for (int i = 0; i < 40; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.print(list);
},String.valueOf(i)).start();
}
}
}
解决方法:
1不用ArrayList 改用vector集合(原因vertor里的add方法加了synchronized,同一时刻只允许一个线程访问和修改)
-
2使用java.util.Collections工具类,它提供了对List Map Set的封装,使其安全
List<Object> list = Collections.synchronizedList(new ArrayList<>());
3使用java.util.Concurrent里有一些如CopyOnWriteArrayList,CopyOnWriteSet的包装型ArrayList();(好处可以并发的读)
挖掘CopyOnWriteArrayList:(写时复制-读写分离)
add
CopyOnWriteArrayList与Collections.synchronizedList的性能对比(转)
写操作:在线程数目增加时CopyOnWriteArrayList的写操作性能下降非常严重,而Collections.synchronizedList虽然有性能的降低,但下降并不明显。
读操作:在多线程进行读时,Collections.synchronizedList和CopyOnWriteArrayList均有性能的降低,但是Collections.synchronizedList的性能降低更加显著