CopyOnWriteArrayList is a class in Java that is part of the `java.util.concurrent` package. It is a thread-safe variant of the `ArrayList` class. The key feature of `CopyOnWriteArrayList` is that it provides a way to achieve thread-safety without the need for explicit synchronization.
Here's how CopyOnWriteArrayList works:
1. Copy-On-Write Strategy: When an element is added, modified, or removed from the `CopyOnWriteArrayList`, a new copy of the underlying array is created. This new copy is then modified with the required changes. This strategy ensures that the original array remains unchanged, providing a consistent view of the data for any currently iterating threads.
2. Reads are Non-blocking: The reading operations (such as `get` and `iterator`) operate on the current underlying array without acquiring any locks. This makes the read operations very fast and suitable for situations where reads are more frequent than writes.
3. Iterators are Snapshot Iterators: The iterators returned by `CopyOnWriteArrayList` traverse the elements of the list at the time the iterator was created. They do not reflect any subsequent changes made to the list. This behavior is consistent with the "snapshot" style iterators.
Because of these characteristics, `CopyOnWriteArrayList` is particularly useful in scenarios where reads are much more frequent than writes, and where the overhead of creating a new copy of the array on each write operation is acceptable.
It's important to note that while `CopyOnWriteArrayList` provides thread-safety for certain use cases, it might not be suitable for all scenarios. It is more efficient for situations where the list is rarely modified compared to the number of read operations.
CopyOnWriteArrayList Example:
package com.javainspires.examples;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ExampleMain{
public static void main(String[] args) throws InterruptedException {
// Creating a CopyOnWriteArrayList
List<String> copyOnWriteList = new CopyOnWriteArrayList<>();
// Adding elements to the list
copyOnWriteList.add("Java");
copyOnWriteList.add("Python");
copyOnWriteList.add("C++");
copyOnWriteList.add("JavaScript");
// Creating a thread for reading the elements
Thread readerThread = new Thread(() -> {
Iterator<String> iterator = copyOnWriteList.iterator();
while (iterator.hasNext()) {
String language = iterator.next();
System.out.println("readerThread Reading: " + language);
try {
// Introducing a delay to simulate other operations
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// Creating a thread for writing (modifying) the list
Thread writerThread = new Thread(() -> {
// Modifying the list by adding a new element
copyOnWriteList.add("Ruby");
System.out.println("writerThread Added: Ruby");
System.out.println(copyOnWriteList);
try {
// Introducing a delay to simulate other operations
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Modifying the list by removing an element
copyOnWriteList.remove("C++");
System.out.println("writerThread Removed: C++");
System.out.println(copyOnWriteList);
});
// Starting both threads
readerThread.start();
writerThread.start();
}
}
In this example, the `CopyOnWriteArrayList` is used to store a list of programming languages. The `readerThread` simulates a continuous read operation on the list, while the `writerThread` performs write operations (add and remove) with delays to showcase the thread-safety of the `CopyOnWriteArrayList`. As the name suggests, a copy of the underlying array is made during write operations, ensuring that reads are not affected by ongoing writes.
Remember that while `CopyOnWriteArrayList` is efficient for scenarios with many reads and few writes, it might not be the best choice for scenarios with frequent write operations due to the overhead of creating copies of the array.