CopyOnWriteArrayList使用记录
最近在编写弹窗层级的时候,写了一个方法,就是在遍历集合,取出集合中的对象,然后网络请求,当请求回来的时候,更改集合状态,代码如下
//遍历集合 并做异步加载
for (IHomeDialog dialog : thisLevelDialogs) {
//判断当前弹窗是否需要校验
if (dialog.needToAgainCheck()) {
//去网络加载
dialog.loadInterface(new HomeDialogNetCallBack() {
@Override
public void loadError(IHomeDialog dialog) {
//改变thisLevelDialogs的集合状态
doSomethings();
}
@Override
public void loadNeedShow(IHomeDialog dialog) {
//改变thisLevelDialogs的集合状态
doSomethings();
}
@Override
public void loadNotNeed(IHomeDialog dialog) {
//改变thisLevelDialogs的集合状态
doSomethings();
}
});
}
}
然而...崩溃了(ConcurrentModificationException )
转念一想,也对,ArrayList是非线性安全,此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。即在一方在便利列表,而另一方在修改列表时,会报ConcurrentModificationException错误。而这不是唯一的并发时容易发生的错误,在多线程进行插入操作时,由于没有进行同步操作,容易丢失数据。但是加锁吧,觉得太重量级。用Vector吧,我度娘后发现,这玩意过时了。不建议使用。
接下来,引入了Collections.synchronizedList和CopyOnWriteArrayList
在一波查询后发现,(下面是我复制的)
CopyOnWriteArrayList和Collections.synchronizedList是实现线程安全的列表的两种方式。两种实现方式分别针对不同情况有不同的性能表现,其中CopyOnWriteArrayList的写操作性能较差,而多线程的读操作性能较好。而Collections.synchronizedList的写操作性能比CopyOnWriteArrayList在多线程操作的情况下要好很多,而读操作因为是采用了synchronized关键字的方式,其读操作性能并不如CopyOnWriteArrayList。因此在不同的应用场景下,应该选择不同的多线程安全实现类。
我选择了CopyOnWriteArrayList,我主要是进行读写,而且没几个数据,不怕效率低下。(而且在代码上省事)
好吧到此问题应该解决了。
但是我在后面做了个排序,也就是sort操作,然后java.lang.UnsupportedOperationException
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
list.add("1");
list.add("2");
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s, String t1) {
return (s.length() - t1.length());
}
});
好吧,又查询了下,CopyOnWriteArrayList不支持set,然后只能贼无奈的找个集合遍历完,然后塞进去。
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();
ArrayList<String> resList = new ArrayList<>();
resList.add("1");
resList.add("2");
resList.add("2");
Collections.sort(resList, new Comparator<String>() {
@Override
public int compare(String s, String t1) {
return (s.length() - t1.length());
}
});
list.addAll(resList);
到此为止,记录下,下次再记录。