CopyOnWriteArrayList 太慢

Cod*_*roc 0 java performance thread-safety copyonwritearraylist

我有以下案例,

public class Test {

    private static final int MAX_NUMBER = 10_00_00;

    public static void main(String[] args) {
        List<Integer> list = new CopyOnWriteArrayList<>();

        long start = System.nanoTime();
        for(int i = 0; i < MAX_NUMBER; i++) {
            list.add(i * 2);
        } 
        long end = System.nanoTime();
        System.out.println(((end - start) / Math.pow(10, 9)));
    }

}
Run Code Online (Sandbox Code Playgroud)

输出

6.861539857
Run Code Online (Sandbox Code Playgroud)

与大约花费的时间相比,它添加元素的速度相当。我在文档中知道了原因,ArrayList0.004690843

一种线程安全的变体,ArrayList其中所有可变操作(添加、设置等)都是通过制作底层数组的新副本来实现的。

所以,我的理解是,每当我在此列表中添加新元素时,它都会创建新的新数组并在该数组的最后一个索引处添加元素。我发现add方法中有一个锁,除此之外,该方法实际上每次都创建新的数组。

当我增加到MAX_NUMBER10_00_000的程序继续运行并且永远不会结束(它会,但我不能等这么久)。

我认为Collections.synchronizedList当您想要线程安全和速度时这是更好的选择。我用了它,花了大约0.007673728

我的问题:

  1. 为什么它在内部创建新数组,线程安全与此有关吗?
  2. 为什么在这种情况下要花这么多时间MAX_NUMBER = 10_00_000?(因为它花了大约 6 秒MAX_NUMBER = 10_00_00)发生这种情况是因为变异操作每次都会创建新数组吗?
  3. 这是否意味着CopyOnWriteArrayList当您有大量元素并且最好选择其他元素(即Collections.synchronizedList)时会出现性能缺陷?
  4. CopyOnWriteArrayList这就是我们通常在公共 API 中看不到的原因吗?除此之外还有什么缺点吗?

dev*_*per 6

CopyOnWriteArrayList仅当写入次数非常少且读取次数巨大时(如果多个线程正在访问此列表),才是首选选项