首页 > 解决方案 > 如何使 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)

标签: javaarraylistconcurrencythread-safetyconcurrentmodification

解决方案


您必须同步对列表的所有访问:

public void destory() {
    synchronized (list) {
      list.stream().toArray(String[]::new);
    }
    System.out.println("done");

}

    while(true) {
      synchronized (list) {
        list.add("test");
      }
    }

请注意,仅将列表包装在 中是不够的Collections.synchronizedList,因为这不会在流的整个迭代中保持监视器。


推荐阅读