Java - The CopyOnWriteArrayList Class Tutorial


CopyOnWriteArrayList is a concurrent Collection class introduced in Java 5 Concurrency API. CopyOnWriteArrayList implements List interface like, ArrayList, Vector, and LinkedList but it is thread-safe collection and it achieves its thread-safety in a slightly different way than Vector and other thread-safe Collection class. As name suggests CopyOnWriteArrayList creates copy of underlying ArrayList with every mutation operation like add or set. ArrayList class is fail-fast which means that if the ArrayList will be changed while some thread is traversing over it using iterator, the iterator.next() will throw a ConcurrentModificationException. But Iterator of CopyOnWriteArrayList is fail-safe and doesn't throw ConcurrentModificationException even if underlying CopyOnWriteArrayList is modified once Iteration begins because Iterator is operating on separate copy of ArrayList. Consequently all the updates made on CopyOnWriteArrayList is not available to Iterator. Let have a simple Example on ArrayList ConcurrentModificationException:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayListIterator {

    public static void main(String[] args) {
        List myList = new ArrayList();
        myList.add("1");
        myList.add("2");
        myList.add("3");
        myList.add("4");
        myList.add("5");

        Iterator it = myList.iterator();
        while (it.hasNext()) {
            String value = it.next();
            System.out.println("List Value:" + value);
            //if(value.equals("3")) myList.remove(value);
        }

    }
}

In the above example if we uncomment the "if" condition, you will get an exception saying the following:

List Value:1
Exception in thread "main" java.util.ConcurrentModificationException
List Value:2
List Value:3
        at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
        at java.util.AbstractList$Itr.next(AbstractList.java:343)
        at com.i3soft.list.ArrayListIterator.main(ArrayListIterator.java:19)
Java Result: 1

Since we are updating the size of the list, its size has not been changed and we are updating the value of the existing element we are not getting ConcurrentModificationException.

To Avoid ConcurrentModificationException in multi-threaded environment:

  1. You can convert the list to an array and then iterate on the array. This approach works well for small or medium size list but if the list is large then it will affect the performance a lot.
  2. You can lock the list while iterating by putting it in a synchronized block. This approach is not recommended because it will cease the benefits of multithreading.
  3. If you are using JDK1.5 or higher then you can use CopyOnWriteArrayList class. It is the recommended approach.

Difference between CopyOnWriteArrayList and ArrayList:

  1. The main difference between these two is, CopyOnWriteArrayList is achieves thread-safe Collectiopn and it is create a separate copy of List for each write operation. The ArrayList is not thread-safe and can not be used in multi-threaded environment.
  2. ArrayList class is fail-fast which means that if the ArrayList will be changed while some thread is traversing over it using iterator, the iterator.next() will throw a ConcurrentModificationException. But Iterator of CopyOnWriteArrayList is fail-safe and doesn't throw ConcurrentModificationException even if underlying CopyOnWriteArrayList is modified once Iteration begins because Iterator is operating on separate copy of ArrayList.
  3. The Iterator of ArrayList supports remove() operation while CopyOnWriteArrayList does not support remove operation, if you do the CopyOnWriteArrayList throws UnsupportedOperationException.

CopyOnWriteArrayList Example:

Here is the complete code example of the CopyOnWriteArrayList.

package com.cs.list;

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

public class CopyOnWriteArrayListIterator {
    public static void main(String [] args){
        CopyOnWriteArrayList myList = new CopyOnWriteArrayList();

        myList.add("1");
        myList.add("2");
        myList.add("3");
        myList.add("4");
        myList.add("5");

        Iterator iter = myList.iterator();
        while (iter.hasNext()) {
            String value = iter.next();
            System.out.println("List Value:" + value);
            //iter.remove();
        }
    }
}

If we uncomment in the above code we will get an Exception is showing UnsupportedOperationException, as in the CopyOnWriteArrayList it does not support the remove operation.

List Value:1
Exception in thread "main" java.lang.UnsupportedOperationException
        at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1004)
        at com.i3soft.list.CopyOnWriteArrayListIterator.main(CopyOnWriteArrayListIterator.java:20)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

No comments

Powered by Blogger.