在我的程序中,我有一个类似于下面的逻辑,它抛出的是 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
,因为这不会在整个迭代的过程中由流来保持监控。