Saturday, August 7, 2021

How to use CopyOnWriteArraySet in Java with Example

CopyOnWriteArraySet is little brother of CopyOnWriteArrayList class. These are special purpose collection classes which was added on JDK 1.5, along with their most popular cousin ConcurrentHashMap. They are part of concurrent collection framework and reside in java.util.concurrent package. CopyOnWriteArraySet is best suited as a read-only collection whose size is small enough to copy if some mutative operation happens, for example, you can use CopyOnWriteArraySet to store objects at the start-up of the application and let multiple application thread access them during application life time. If an new condition or object comes up during that time, it can also be added into this Set, with incurring cost of creating a new array.

One of the most important thing to know about CopyOnWriteArraySet is that it is backed by CopyOnWriteArrayList, which means it also share all basic properties of CopyOnWriteArrayList.

Another important thing to remember is that Iterators of this collection class doesn't support remove() operation, trying to remove an element while iterating will result in UnSupportedOperationException.

This is done to ensure speed during traversal, traversing this set implementation using Iterator is fast and cannot encounter interference from other threads. Iterators actually rely on unchanging snapshots of the array at the time the iterators were constructed.

In short, use CopyOnWriteArraySet if set is small enough to copy on add, set or remove, and main purpose is to read data with occasional updates. Also if you want to remove elements during iteration, don't use this Set implementation because its iterator doesn't support remove(), and throws java.lang.UnsupportedOperationException as shown below :
[RAJ] Event received : FOUR 
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.concurrent.CopyOnWriteArrayList$COWIterator
    .remove(Unknown Source)
    at Publisher.notifySubs(HelloHP.java:43)
    at HelloHP.main(HelloHP.java:23)



CopyOnWriteArraySet Example in Java

Here is our complete Java program to show how to use CopyOnWriteArraySet. In our example, we have used publisher subscriber pattern to demonstrate its use. Most of the subscribers subscribed during start-up and main task of publisher is to iterate over them and notify them with any updates. Occasional addition and deletion of Subscriber is also possible. 

Since we need fast traversal, CopyOnWriteArraySet is a good choice, especially in multi-threaded environment where one thread can add subscriber, while other thread is processing updates.

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Java program to demonstrate how to use CopyOnWriteArraySet in Java.
 *  Remember,
 * CopyOnWriteArraySet doesn't support remove() operation.
 *
 * @author Javin Paul
 */
public class CopyOnWriteArraySetDemo{

    public static void main(String args[]) {
        Publisher cricNext = new Publisher();

        SubScriber raj = new SubScriber("RAJ");
        SubScriber adom = new SubScriber("ADOM");

        cricNext.addSubscriber(raj);
        cricNext.addSubscriber(adom);

        cricNext.notifySubs("FOUR");
        cricNext.notifySubs("SIX");

    }

}

class Publisher {

    private CopyOnWriteArraySet setOfSubs = new CopyOnWriteArraySet();

    public void addSubscriber(SubScriber sub) {
        setOfSubs.add(sub);
    }

    public void notifySubs(String score) {
        Iterator itr = setOfSubs.iterator();
        while (itr.hasNext()) {
            SubScriber sub = itr.next();
            sub.receive(score);

            //itr.remove(); // not allowed, 
              throws UnsupportedOperationException
        }
    }
}

class SubScriber {

    private String _name;

    public SubScriber(String name) {
        this._name = name;
    }

    public void receive(String score) {
        System.out.printf("[%s] Event received : %s %n", _name, score);
    }
}


Output:
[RAJ] Event received : FOUR 
[ADOM] Event received : FOUR 
[RAJ] Event received : SIX  
[ADOM] Event received : SIX


Things to remember about CopyOnWriteArraySet

CopyOnWriteArraySet implements Collection and Set interface, and added on JDK 1.5 along with another special Set implementation, EnumSet. This is also a Set that uses an internal CopyOnWriteArrayList for all of its operations. Thus, it shares the same basic properties of that class. It's not a SortedSet thus order of elements is not guaranteed during iteration.

CopyOnWriteArraySet Example in Java

1) CopyOnWriteArraySet is best suited for applications in which set sizes generally stay small, read-only operations vastly outnumber mutative operations, and you need to prevent interference among threads during traversal.

2) Another benefit of CopyOnWriteArraySet is thread-safety, it's a concurrent collection.
3) Mutative operations (add, set, remove, etc.) are expensive since they usually require copying the entire underlying array.

4) Iterators do not support the mutative remove operation.
5) Traversal via iterators is fast and cannot encounter interference from other threads. Iterators rely on unchanging snapshots of the array at the time the iterators were constructed.


That's all on How to use CopyOnWriteArraySet in Java. As I said its a little brother of CopyOnWriteArrayList, so if you understand one of them, you can use others. Only difference being these two are one is List and other is Set, but that brings all difference between Set and List in Java.

For example, List is ordered, allows duplicate while Set is unordered, but doesn't allow duplicate. Always remember that CopyOnWriteArraySet is a special purpose Collection class, and you should only use it when conditions are favourable, otherwise stick with general purpose Set implementation e.g. HashSet, LinkedHashSet or synchronized collection classes.


2 comments :

Anonymous said...

What happens to an add operation during iteration?

Ramesh Babu Y said...

on the iterator we do not have the add method and if you use add method directly on the CopyOnWriteArraySet , yes u can add the entry during iteration , no issue

Post a Comment