Get started with CopyOnWriteArrayList

The CopyOnWriteArrayList class allows to quickly (no synchronization required) iterate over a list while other threads have the possibility to insert elements to it meanwhile. The following example shows that you simply can’t do that with an ordinary ArrayList:

import java.util.*;
  
public class Main
{
   public static void main(String[] args) {
      ArrayList<String> al = new ArrayList<String>();
     
      new Thread(new Producer(al)).start();
        
      try { Thread.sleep(100); } catch(Exception e) { }
        
      Iterator iter = al.iterator();
      while (iter.hasNext()) {
         System.out.println(iter.next());
      }
   }
}
  
class Producer implements Runnable
{
   private ArrayList<String> al = null;
 
   public Producer(ArrayList<String> al) {
      this.al = al;
   }
  
   public void run() {
      for (int i=0; i<100000; i++) {
         String message = "element #" + i;
         //System.out.println("Adding " + message);
         al.add(message);         
      }
   }
}

outputs, in one run:

element #0
element #1
element #2
element #3
element #4
element #5
element #6
element #7
element #8
element #9
Exception in thread "main" java.util.ConcurrentModificationException
        at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:449)
        at java.util.AbstractList$Itr.next(AbstractList.java:420)
        at Main.main(Main.java:14)

The new java.util.concurrent.CopyOnWriteArrayList solves this problem, but comes at a cost. The CopyOnWriteArrayList makes an entire copy of the underlying array every time it is modified. Only those methods are synchronized.

The following example creates a Producer that continually puts messages on an ArrayList. The other (main) thread waits for a bit, then requests an iterator on the ArrayList. This causes the reference of the original array to be copied into an instance of the internal private (to CopyOnWriteArray) class COWIterator. Any modification performed on the CopyOnWriteArrayList object will not interfere as a new array is instantiated and the old array is copied into it (with System.arraycopy).

Main.java:

import java.util.concurrent.*;
import java.util.*;
  
public class Main
{
   public static void main(String[] args) {
      CopyOnWriteArrayList<String> al = new CopyOnWriteArrayList<String>();
     
      new Thread(new Producer(al)).start();
        
      try { Thread.sleep(10); } catch(Exception e) { }
        
      int counter = 0;
      Iterator iter = al.iterator();
      while (iter.hasNext()) {
         iter.next();
         counter++;
      }
      System.out.println("Iterator returned " + counter + " elements");
   }
}
  
class Producer implements Runnable
{
   private CopyOnWriteArrayList<String> al = null;
 
   public Producer(CopyOnWriteArrayList<String> al) {
      this.al = al;
   }
 
   public void run() {
      for (int i=0; i<100000; i++) {
         String message = "element #" + i;
         //System.out.println("Adding " + message);
         al.add(message);  
      }
   }
}

- How do I easily print out the contents of a one-dimensional array in JDK 1.5?

The old way:

import java.util.*;
 
public class Main
{
   public static void main(String []args) {
      Message[] messages = new Message[10];
      for (int i=0; i<10; i++) {
         Message m = new Message("contents #" + i);
         messages[i] = m;
      }
       
      System.out.println(messages);  // damn, prints out something like [LMessage;@10b62c9 
                                     // need to iterate over the array      
   }
}
 
class Message
{
   String contents = null;
 
   public Message(String contents) {
      this.contents = contents;
   }
    
   public String toString() {
      return contents;
   }
}

The new way:

import java.util.*;
 
public class Main
{
   public static void main(String []args) {
      Message[] messages = new Message[10];
      for (int i=0; i<10; i++) {
         Message m = new Message("contents #" + i);
         messages[i] = m;
      }
       
      System.out.println(Arrays.toString(messages));
   }
}
 
class Message
{
   String contents = null;
 
   public Message(String contents) {
      this.contents = contents;
   }
    
   public String toString() {
      return contents;
   }
}

prints out:

[contents #0, contents #1, contents #2, contents #3, contents #4, contents #5, 
contents #6, contents #7, contents #8, contents #9]