java - 如何使 java.util.ArrayList 线程安全
问题描述
我的程序中有类似于下面的逻辑,它会抛出ConcurrentModificationException
. 除了使用之外,我怎样才能使java.util.ArrayList
线程安全CopyOnWriteArrayList
(因为我在这个列表上有大量的写入,并且据我所知,CopyOnWriteArrayList 上的写入很昂贵)
import java.util.ArrayList;
import java.util.List;
public class Test extends Thread {
List<String> list = new ArrayList<String>();
public static void main(String[] args) {
Test t = new Test();
t.start();
System.out.println("in main thred");
t.destory();
}
public void destory() {
list.stream().toArray(String[]::new);
System.out.println("done");
}
@Override
public void run() {
while(true) {
list.add("test");
}
}
}
输出:
in main thred
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1388)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:546)
at java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260)
at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:438)
解决方案
您必须同步对列表的所有访问:
public void destory() {
synchronized (list) {
list.stream().toArray(String[]::new);
}
System.out.println("done");
}
和
while(true) {
synchronized (list) {
list.add("test");
}
}
请注意,仅将列表包装在 中是不够的Collections.synchronizedList
,因为这不会在流的整个迭代中保持监视器。
推荐阅读
- laravel - Laravel Newsletter 包错误:尝试访问 bool 类型值的数组偏移量
- php - 从 PHP &_POST 为复选框创建一个动态数组以在 foreach 循环中使用
- c - malloc 函数上的程序崩溃 - 语法正确,不知道为什么
- html - 仅当特定函数以角度调用时如何在页面上显示数据
- facebook - HybridAuth Facebook 无效范围:数组(请检查小写字母或分隔符)
- c - c 的 void* 作为参数和返回值
- sql - Oracle:根据变量和历史表获取价格
- c++ - 如何使用cmd链接不同目录的目标文件?
- java - Hibernate - JPA - OneToMany 和 CascadeType.ALL
- android-studio - 如何在android中将一个类的方法调用到另一个类