Threads Java

//package org.j4me.collections;
/**
 * Stores a single object for the producer/consumer pattern and takes care
 * of thread synchronization.  A first thread, the producer, can put an object
 * into the cubby hole using set.  If there already is an object
 * in the cubby hole then it is discarded.  Meanwhile a second thread, the
 * consumer, can get the object using get.  If no object is in
 * the cubby hole the consumer will block until one is available.
 * 


 * CubbyHole is valuable for several situations including where
 * a lot of information is produced and consumption is time consuming.  For
 * example an application that does expensive rendering based on location
 * events could only render based on the very latest location.   
 */
public class CubbyHole
{
  /**
   * The object stored by the producer.  If this is null
   * there is nothing to consume.
   */
  private Object cubby;
  /**
   * Called by the producer to put data into the cubby hole.
   * If there was another object stored in the cubby hole it will be
   * removed and returned.
   * 


   * This is a thread-safe method that returns immediately.  If another
   * thread, acting as the consumer, is blocking on get it
   * will start running so long as data is not null.
   *  
   * @param data is the information to store in the cubby hole.  If
   *  null then there is no job and any calls to get
   *  will block until set is called again with a non-
   *  null object.
   * @return The object in the cubby hole replaced by data
   *  or null if nothing was stored.
   */
  public synchronized Object set (Object data)
  {
    Object ret = cubby;
    cubby = data;
    // Unblock a consumer waiting on get().
    notifyAll();
    
    return ret;
  }
  /**
   * Called by the consumer to get an object stored in the cubby hole.
   * If nothing is stored this thread will block until set
   * is called by a different thread.
   * 
   * @return The object stored in the cubby hole by a call to set.
   *  This will never return null.
   * @throws InterruptedException if the program is exiting.
   */
  public synchronized Object get ()
    throws InterruptedException
  {
    // Block until a job is available.
    while ( cubby == null )
    {
      wait();  // Releases the lock on this when waiting and re-acquires when awaken
    }
    // Get the data in the cubby hole.
    Object ret = cubby;
    cubby = null;
    return ret;
  }
  /**
   * Looks at the cubby hole without removing the object from it.  This
   * is a non-blocking method.
   *  
   * @return The object in the cubby hole which will be null
   *  if nothing is being stored.
   */
  public synchronized Object peek ()
  {
    return cubby;
  }
  /**
   * Test is the cubby hole is empty.  This is a non-blocking method.
   * 
   * @return true if nothing is in the cubby hole or 
   *  false
 if it has an object.
   */
  public synchronized boolean empty ()
  {
    return (cubby == null);
  }
}
---------------
package org.j4me.collections;
import org.j4me.*;
import j2meunit.framework.*;
/**
 * Tests the CubbyHole class.  It is a thread synchronization
 * helper that stores exactly one object.  A worker thread can get the very
 * latest information stored by a producer.
 * 
 * @see org.j4me.collections.CubbyHole
 */
public class CubbyHoleTest
  extends J4METestCase
{
  public CubbyHoleTest ()
  {
    super();
  }
  
  public CubbyHoleTest (String name, TestMethod method)
  {
    super( name, method );
  }
  
  public Test suite ()
  {
    TestSuite suite = new TestSuite();
    
    suite.addTest(new CubbyHoleTest("testBasics", new TestMethod() 
        { public void run(TestCase tc) {((CubbyHoleTest) tc).testBasics(); } }));
    suite.addTest(new CubbyHoleTest("testBlocking", new TestMethod() 
        { public void run(TestCase tc) {((CubbyHoleTest) tc).testBlocking(); } }));
    
    return suite;
  }
  
  /**
   * Tests that a cubby hole stores exactly one object.  Thread synchronization
   * is not covered by this test case.
   */
  public void testBasics ()
  {
    try
    {
      CubbyHole cubby = new CubbyHole();
      
      // Very there is nothing in the empty cubby hole.
      boolean isEmpty = cubby.empty();
      assertTrue("The cubby hole is empty.", isEmpty);
      
      Object peek = cubby.peek();
      assertNull("Nothing comes from peaking into an empty cubby hole.", peek);
      
      // Put something into the cubby hole.
      Integer i = new Integer( 13 );
      cubby.set( i );
      
      isEmpty = cubby.empty();
      assertFalse("The cubby hole has something in it.", isEmpty);
      
      peek = cubby.peek();
      assertSame("The cubby hole correctly stored our object.", i, peek);
  
      Object get = cubby.get();
      assertSame("Got the object stored in the cubby.", i, get);
  
      // The cubby hole should once again be empty.
      isEmpty = cubby.empty();
      assertTrue("The cubby hole is empty again.", isEmpty);
      
      peek = cubby.peek();
      assertNull("Nothing comes from peaking into the empty again cubby hole.", peek);
  
      // Put several objects into the cubby hole before taking one out.
      Integer i1 = new Integer( 1 );
      Integer i2 = new Integer( 2 );
      Integer i3 = new Integer( 3 );
      
      get = cubby.set( i1 );
      assertNull("Nothing returned from empty cubby hole.", get);
  
      get = cubby.set( i2 );
      assertSame("Old data i1 returned from cubby hole.", i1, get);
  
      get = cubby.set( i3 );
      assertSame("Old data i2 returned from cubby hole.", i2, get);
  
      get = cubby.get();
      assertSame("Newest data is in cubby hole.", i3, get);
    }
    catch (InterruptedException e)
    {
      fail( e.toString() );
    }
  }
  
  /**
   * Tests that a consumer thread blocks waiting for a producer to add
   * something to the cubby hole.
   */
  public void testBlocking ()
  {
    final CubbyHole one = new CubbyHole();
    final CubbyHole two = new CubbyHole();
    
    class Consumer extends Thread
    {
      public void run ()
      {
        try
        {
          // Block waiting for something in the first cubby hole.
          Object consume = one.get();
          
          // The producer thread should be blocking waiting for
          // this thread to put something into the second cubby hole.
          two.set( consume );
        }
        catch (Throwable t)
        {
          fail( t.toString() );
        }
      }
    }
    
    try
    {
      // Create a consumer thread.
      Consumer consumer = new Consumer();
      consumer.start();
      
      // Give up the CPU to let the consumer start and block.
      Thread.sleep( 0 );
      // Put some data into the first cubby hole to unblock the consumer.
      Integer data = new Integer( 13 );
      one.set( data );
      
      // Get data from the second cubby hole.  This thread will block
      // until the consumer puts something into it.
      Integer result = (Integer)two.get();
      
      // Verify the consumer thread read our original data from the
      // first cubby hole and put it into the second.
      assertSame("Data integrety verified.", data, result);
    }
    catch (InterruptedException e)
    {
      fail( e.toString() );
    }
  }
}