javaperformancethread-safetycopyonwritearraylist

CopyOnWriteArrayList is too slow


I have following case,

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)));
    }

}

OUTPUT

6.861539857

It adds element quite slowly compared to ArrayList which took approximately 0.004690843. I came to know the reason in the documentation,

A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.

So, my understanding is, whenever I add new element in this list it will create new fresh array and add element at last index of this array. I find a lock in add method and apart from that that method is actually creating new array every time.

When I increased MAX_NUMBER to 10_00_000 my programs keeps on running and never end (it would but I can't wait for so long).

I think Collections.synchronizedList is the better choice when you want thread safety with speed. I used it and it took about 0.007673728.

My questions :

  1. Why internally it create new array does thread safety is related to this ?
  2. Why it took so much time in case of MAX_NUMBER = 10_00_000 ? (as it took about 6 seconds with MAX_NUMBER = 10_00_00) Is this happening because mutative operation creates new array every time ?
  3. Does this mean CopyOnWriteArrayList has performance drawback when you have huge number of elements and better to choose something else (i.e. Collections.synchronizedList)?
  4. Is this the reason we usually don't see CopyOnWriteArrayList in public APIs ? Is there any drawbacks other than this ?

Solution

  • CopyOnWriteArrayList is the preferred option ONLY WHEN there are very less number of writes and huge number of reads (if multiple threads are accessing this list)