本篇介绍一个知识点-CopyOnWriteArrayList
它是一个线性安全的集合,可同时进行读写修改的List
- 举两个例子:
fun formatModels(data : MutableList<GetTemplateResp.DataDTO>?) : MutableList<GetTemplateResp.DataDTO>?{
if(data != null && data.size > 0){
var tempList = CopyOnWriteArrayList(data)
for(item in tempList){
if(item.userDeviceTemplateInfoVoList == null || item.userDeviceTemplateInfoVoList.size > chooseDeviceList!!.size){
tempList.remove(item)
}
}
return tempList
}else{
return null
}
}
这里的tempList 我在便利的同时一边在删除数据,其它集合做不到。再看另一个例子
private static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
@SneakyThrows
public static void main(String[] args) {
// 创建新增元素线程
Thread thread1 = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
for (int i = 0; i < 8; i++) {
list.add("element-" + i);
log.info("添加元素 element-{}", i);
Thread.sleep(100);
}
}
});
// 创建删除元素线程
Thread thread2 = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
for (int i = 0; i < 5; i++) {
if(list.size() > 0){
list.remove(0);
log.info("删除元素----- element-{}", i);
}
Thread.sleep(200);
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
log.info("list中的最终元素:{}", list);
// 遍历元素
for (String element: list){
log.info("打印元素:{}", element);
}
}
运行结果如下:
23:03:24.187 [Thread-0] - 添加元素 element-0
23:03:24.187 [Thread-1] - 删除元素----- element-0
23:03:24.296 [Thread-0] - 添加元素 element-1
23:03:24.397 [Thread-1] - 删除元素----- element-1
23:03:24.397 [Thread-0] - 添加元素 element-2
23:03:24.498 [Thread-0] - 添加元素 element-3
23:03:24.600 [Thread-1] - 删除元素----- element-2
23:03:24.600 [Thread-0] - 添加元素 element-4
23:03:24.703 [Thread-0] - 添加元素 element-5
23:03:24.805 [Thread-1] - 删除元素----- element-3
23:03:24.807 [Thread-0] - 添加元素 element-6
23:03:24.909 [Thread-0] - 添加元素 element-7
23:03:25.007 [Thread-1] - 删除元素----- element-4
23:03:25.211 [main] - list中的最终元素:[element-5, element-6, element-7]
23:03:25.212 [main] - 打印元素:element-5
23:03:25.212 [main] - 打印元素:element-6
23:03:25.212 [main] - 打印元素:element-7
这里简单说一下它的原理吧,先看一组图:
比如你正在使用它进行add()添加元素,它实际上是把原数据copy(复制)了一份出来,在新的数组里面进行操作;同样的你在进行remove的时候或者update的时候也是同理,它实际上不是直接操作的原数据源,而是拷贝出来操作,这样就不会出现索引越界或者同时读取边删除的错误了,这也是为什么说它是线性安全的原因了。
看两个源码:
对于没用过这个东西或者初学者来说,结合我对它的介绍和源码,一目了然,它始终操作的新拷贝的数据,然后把新整理好的数据返回给外层,在公司项目开发中难免会有这种情况,用这个很方便。
这里补充一点,普通ArrayList如何直接转换成CopyOnWriteArrayList,如果项目中已经用的是普通的ArrayList,不用重新写,如下:
Kotlin:
var arry = arrayListOf()
var copyList = CopyOnWriteArrayList(arry)
Java:
List aList = new ArrayList<>();
aList.add(“1”);
aList.add(“2”);
aList.add(“3”);
aList.add(“4”);
CopyOnWriteArrayList copyList = new CopyOnWriteArrayList(aList.toArray());或者
List aList = new ArrayList<>();
aList.add(“1”);
aList.add(“2”);
aList.add(“3”);
aList.add(“4”);
CopyOnWriteArrayList copyList = new CopyOnWriteArrayList(aList);
这里说一下大概的使用场景吧,可能不全,说个大概吧,自己根据自己实际情况使用:
1.例如要操作并发处理的时候(比如消息并发)
2.多个线程同时访问一个数据源的时候
3.项目不大,可以不需要自己去封装一套消息队列的时候,可以用它来处理。
4.集合中需要进行比较和剔除
总之,同时读取和删除、更新的时候可以用它。
本篇完。
版权归原作者 没有笔的小新是路飞。 所有, 如有侵权,请联系我们删除。