CopyOnWriteArrayList
in Java implements the List interface just like its other well known counterpart
ArrayList and is part of java.util.concurrent
package. How CopyOnWriteArrayList differs from ArrayList is that it is a thread-safe variant of ArrayList.
For more differences between CopyOnWriteArrayList and ArrayList in Java refer this post- Difference Between ArrayList And CopyOnWriteArrayList in Java
- How is Java CopyOnWriteArrayList thread-safe
- Java CopyOnWriteArrayList constructors
- Java example creating a CopyOnWriteArrayList
- CopyOnWriteArrayList returns a fail-safe iterator
- CopyOnWriteArrayList iteration example
- Iterator’s add, remove method not permitted in CopyOnWriteArrayList
- Advantages and disadvantages of using CopyOnWriteArrayList
How is Java CopyOnWriteArrayList thread-safe
CopyOnWriteArrayList in Java, just like ArrayList, uses an array of type Object to store its elements. For thread safety, implementation of CopyOnWriteArrayList, as its name suggests, creates a new copy of the underlying array for any modification operation like add, set, replace etc.
That makes CopyOnWriteArrayList a good choice when there are more traversal operations than the mutations, as the List can be iterated along with concurrent modifications with out any inference as the iteration will be done on a separate copy of the List.
Java CopyOnWriteArrayList constructors
- CopyOnWriteArrayList()- Creates an empty list.
- CopyOnWriteArrayList(Collection<? extends E> c)- Creates a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.
- CopyOnWriteArrayList(E[] toCopyIn)- Creates a list holding a copy of the given array.
Java example creating a CopyOnWriteArrayList
Here is a simple example showing how to create CopyOnWriteArrayList and add elements to it.
import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class CopyList { public static void main(String[] args) { //creating CopyOnWriteArrayList List<String> carList = new CopyOnWriteArrayList<String>(); carList.add("Audi"); carList.add("Jaguar"); carList.add("Mini Cooper"); carList.add("BMW"); System.out.println("List elements- " + carList); } }Output
List elements- [Audi, Jaguar, Mini Cooper, BMW]
CopyOnWriteArrayList returns a fail-safe iterator
Iterator returned by CopyOnWriteArrayList in Java is fail-safe which means iterator is guaranteed not to throw ConcurrentModificationException
even if the List is structurally modified at any time after the iterator is created.
When an iterator is created for the CopyOnWriteArrayList it gets an immutable copy of the underlying array which is iterated. This array never changes during the lifetime of the iterator, so interference is impossible.
But note that since iteration is done on a separate copy so any modification in the CopyOnWriteArrayList won’t be reflected while iteration.
CopyOnWriteArrayList iteration example
Let’s see an example of iteration in CopyOnWriteArrayList. To make it clearer first we’ll iterate an ArrayList while it is also modified concurrently by another thread to see what happens in the case of ArrayList then we’ll see the same example using CopyOnWriteArrayList.
public class CopyList { public static void main(String[] args) { //creating CopyOnWriteArrayList List<String> carList = new ArrayList<String>(); carList.add("Audi"); carList.add("Jaguar"); carList.add("Mini Cooper"); carList.add("BMW"); Thread t1 = new Thread(new ItrClass(carList)); Thread t2 = new Thread(new ModClass(carList)); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("List elements in Main- " + carList); } } // Thread class for iteration class ItrClass implements Runnable{ List<String> carList; public ItrClass(List<String> carList){ this.carList = carList; } @Override public void run() { Iterator<String> i = carList.iterator(); while (i.hasNext()){ System.out.println(i.next()); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //Thread class for modifying list class ModClass implements Runnable{ List<String> carList; public ModClass(List<String> carList){ this.carList = carList; } @Override public void run() { System.out.println("Adding new value to the list"); carList.add("Mercedes"); } }Output
Adding new value to the list Audi Exception in thread "Thread-0" java.util.ConcurrentModificationException at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:937) at java.base/java.util.ArrayList$Itr.next(ArrayList.java:891) at com.knpcode.ItrClass.run(CopyList.java:41) at java.base/java.lang.Thread.run(Thread.java:844) List elements in Main- [Audi, Jaguar, Mini Cooper, BMW, Mercedes]
As you can see with ArrayList if list is modified while it is being iterated then the ConcurrentModificationException is thrown.
Using CopyOnWriteArrayListNow we can change the ArrayList to CopyOnWriteArrayList in the same example.
List<String> carList = new CopyOnWriteArrayList<String>();
With that output is
Adding new value to the list Audi Jaguar Mini Cooper BMW List elements in Main- [Audi, Jaguar, Mini Cooper, BMW, Mercedes]
As you can see now ConcurrentModificationException is not thrown but the iterator doesn’t display the newly added element as it is iterating on a separate copy.
Iterator’s add, remove method not permitted in CopyOnWriteArrayList
Making a new copy gives you the convenience to iterate the List without the fear of ConcurrentModificationException
but at the same time iterator’s element-changing operations like remove, set, and add are not supported in
CopyOnWriteArrayList. These methods throw UnsupportedOperationException
.
public class CopyList { public static void main(String[] args) { //creating CopyOnWriteArrayList List<String> carList = new CopyOnWriteArrayList<String>(); carList.add("Audi"); carList.add("Jaguar"); carList.add("Mini Cooper"); carList.add("BMW"); Iterator<String> itr = carList.iterator(); while (itr.hasNext()){ String str = itr.next(); if(str.equals("Jaguar")) { // removing using iterator's remove method itr.remove(); } } } }Output
Exception in thread "main" java.lang.UnsupportedOperationException at java.base/java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(CopyOnWriteArrayList.java:1117) at com.knpcode.CopyList.main(CopyList.java:21)
As you can see using iterator’s remove method here results in UnsupportedOperationException being thrown.
Advantages and disadvantages of using CopyOnWriteArrayList in Java
CopyOnWriteArrayList performs well when there are more traversal operations than the mutations, since you don't need to explicitly synchronize the CopyOnWriteArrayList to iterate it in a multi-threaded environment.
In general using CopyOnWriteArrayList is costly because of the added task of creating copies in case of mutative operations and keep changing the underlying array.
CopyOnWriteArrayList is guaranteed to not throw ConcurrentModificationException even if there are concurrent modifications to the list while iteration. At the same time iterator’s element-changing operations are not supported.
That's all for the topic Java CopyOnWriteArrayList With Examples. If something is missing or you have something to share about the topic please write a comment.
You may also like
- Java CopyOnWriteArraySet With Examples
- ArrayList Vs CopyOnWriteArrayList in Java
- ArrayBlockingQueue in Java With Examples
- Java Volatile Keyword With Examples
- Create a Date Object With Values in Java
- Java try-with-resources With Examples
- How to Read Delimited File in Java
- Introduction to Hadoop Distributed File System (HDFS)
No comments:
Post a Comment