CopyOnWriteArrayList example..

.. where it is used instead of a plain old ArrayList!

We will need the following classes for our example..
Dog.java
public class Dog {
 
    private final String name;
 
    public Dog(final String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return this.name;
    }
}

DogArrayListReader.java
import java.util.List;
import java.util.Iterator;
 
public class DogArrayListReader implements Runnable {
 
    private final List<Dog> dogs;
 
    public DogArrayListReader(final List<Dog> dogs) {
        this.dogs = dogs;
    }
 
    @Override
    public void run() {
        final Iterator<Dog> dogsIterator = dogs.iterator();
 
        try {
            Thread.sleep(250); // Give other threads chance to modify the list
                               // after the iterator has been acquired.
        } catch (InterruptedException ignored) {
            // ignored..
        }
 
        while (dogsIterator.hasNext()) {
            System.out.println(dogsIterator.next());
        }
    }
}

DogArrayListWriter.java
import java.util.List;
 
public class DogArrayListWriter implements Runnable {
 
    private final List<Dog> dogs;
 
    public DogArrayListWriter(final List<Dog> dogs) {
        this.dogs = dogs;
    }
 
    @Override
    public void run() {
        System.out.println("Adding new Dog..");
        dogs.add(new Dog("Dog - 03"));
    }
}

Take 01 - Using Plain Old ArrayList..

TestClass.java
import java.util.List;
import java.util.ArrayList;
 
public class TestClass {
 
    public static void main(String[] args) throws InterruptedException {
        final List<Dog> dogs = new ArrayList<Dog>();
        dogs.add(new Dog("Dog - 01"));
        dogs.add(new Dog("Dog - 02"));
 
        final Thread readerThread = new Thread(new DogArrayListReader(dogs));
        final Thread writerThread = new Thread(new DogArrayListWriter(dogs));
 
        readerThread.start();
        writerThread.start();
 
        readerThread.join();
        writerThread.join();
 
        System.out.println("== Printing Final State ==");
        for (Dog d : dogs) {
            System.out.println(d);
        } 
    }
}

..and the output will be..

Take 02 - Using CopyOnWriteArrayList.

TestClass.java
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
 
public class TestClass {
 
    public static void main(String[] args) throws InterruptedException {
        final List<Dog> dogs = new CopyOnWriteArrayList<Dog>();
        dogs.add(new Dog("Dog - 01"));
        dogs.add(new Dog("Dog - 02"));
 
        final Thread readerThread = new Thread(new DogArrayListReader(dogs));
        final Thread writerThread = new Thread(new DogArrayListWriter(dogs));
 
        readerThread.start();
        writerThread.start();
 
        readerThread.join();
        writerThread.join();
 
        System.out.println("== Printing Final State ==");
        for (Dog d : dogs) {
            System.out.println(d);
        } 
    }
}

..and the output will be..