Wednesday, 30 November 2011

Java 1.4 Collections in Multithreaded Environment

List, Set and Map are not thread-safety by nature. Java 1.5 offers APIs to make it synchronized.
Collections.synchronizedList(new ArrayList());
Collections.synchronizedSet(new Hashset());
Collections.synchronizedMap(new HashMap());

The add/remove methods will become thread-safe by doing as above. One new real problem is "fail-fast". When a thread is iterating over this collections and another thread does add/remove into the same collection, then java.util.ConcurrentModificationException will be thrown.

The above said theory is explained in N number of java papers. But, I'm depicting the fail-fast scenario with an example program. This program is as simple as for self-explanatory.

The below code contains a list and methods to iterate over the list, add elements into it and remove elements from it. Thread t1, t2 and t3 are started together to produce the fail-fast scenario.


package samples.concurrency;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class Sample15_1
{
 private List<String> l = Collections.synchronizedList(new ArrayList<String>());
 private final static int iterationCount = 9000;

 Sample15_1()
 {
  for (int i = 0; i < iterationCount; i++)
  {
   l.add(new String("A" + i));
  }
 }

 public void addName(String str)
 {
  l.add(str);
 }

 public void removeName(String str)
 {
  l.remove(str);
 }

 public void printNames() throws Exception
 {
  int count = 0;
  Iterator<String> i = l.iterator();
  while (i.hasNext())
  {
   count++;
   if (count % 40 == 0)
    System.out.println();
   System.out.print(i.next()+" ");
  }
 }

 public static void main(String[] args) throws Exception
 {
  final Sample15_1 sample = new Sample15_1();
  Thread t1 = new Thread()
  {
   public void run()
   {
    try
    {
     sample.printNames();
    }
    catch (Exception e)
    {
     e.printStackTrace();
    }
   }
  };
  Thread t2 = new Thread()
  {
   public void run()
   {
    for (int i = 0; i < iterationCount; i++)
     sample.addName("B" + i);
   }
  };
  Thread t3 = new Thread()
  {
   public void run()
   {
    for (int i = 0; i < iterationCount; i++)
     sample.removeName("A" + i);
   }
  };
  t3.start();
  t2.start();
  t1.start();
 }
}

No comments:

Post a Comment