Circular Buffer

SharedCell.java

import java.text.DecimalFormat;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class SharedCell extends JFrame {
	JTextArea output = new JTextArea( 20, 30 );

	public SharedCell()
   {
      super( "Demonstrating Thread Synchronization" );

      getContentPane().add( new JScrollPane( output ) );
      setSize( 500, 500 );
      show();

      // set up threads and start threads
      HoldIntegerSynchronized h =
         new HoldIntegerSynchronized( this );
      ProduceInteger p = new ProduceInteger( h, this );
      ConsumeInteger c = new ConsumeInteger( h, this );

      p.start();
      c.start();
   }

   void show(String s)
   {
	   output.append(s);
	   System.out.print(s);
   }

   public static void main( String args[] )
   {
      SharedCell app = new SharedCell();
	  app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
}

ProduceInteger.java

import javax.swing.JTextArea;

public class ProduceInteger extends Thread {
   private HoldIntegerSynchronized pHold;
   private SharedCell output;

   public ProduceInteger( HoldIntegerSynchronized h,
                          SharedCell o )
   {
      super( "ProduceInteger" );
      pHold = h;
      output = o;
   }

   public void run()
   {
      for ( int count = 1; count <= 10; count++ ) {
         // sleep for a random interval
         // Note: Interval shortened purposely to fill buffer
         try {
            Thread.sleep( (int) ( Math.random() * 500 ) );
         }
         catch( InterruptedException e ) {
            System.err.println( e.toString() );
         }

         pHold.setSharedInt( count );
      }

      output.show( "\n" + getName() +
         " finished producing values" +
         "\nTerminating " + getName() );
   }
}

ConsumeInteger.java

// ConsumeInteger.java
// Definition of threaded class ConsumeInteger
import javax.swing.JTextArea;

public class ConsumeInteger extends Thread {
   private HoldIntegerSynchronized cHold;
   private SharedCell output;

   public ConsumeInteger( HoldIntegerSynchronized h,
                          SharedCell o )
   {
      super( "ConsumeInteger" );
      cHold = h;
      output = o;
   }

   public void run()
   {
      int val, sum = 0;

      do {
         // sleep for a random interval
         try {
            Thread.sleep( (int) ( Math.random() * 3000 ) );
         }
         catch( InterruptedException e ) {
            System.err.println( e.toString() );
         }

         val = cHold.getSharedInt();
         sum += val;
      } while ( val != 10 );

      output.show( "\n" + getName() +
         " retrieved values totaling: " + sum +
         "\nTerminating " + getName() + "\n" );
   }
}

HoldIntegerSynchronized.java

import javax.swing.JTextArea;
import java.text.DecimalFormat;

public class HoldIntegerSynchronized {
   private int sharedInt[] = { -1, -1, -1, -1, -1 };
   private boolean writeable = true;
   private boolean readable = false;
   private int readLoc = 0, writeLoc = 0;
   private SharedCell output;

   public HoldIntegerSynchronized( SharedCell o )
   {
      output = o;
   }

   public synchronized void setSharedInt( int val )
   {
      while ( !writeable ) {
         try {
            output.show( " WAITING TO PRODUCE " + val );
            wait();
         }
         catch ( InterruptedException e ) {
            System.err.println( e.toString() );
         }
      }

      sharedInt[ writeLoc ] = val;
      readable = true;

      output.show( "\nProduced " + val +
                     " into cell " + writeLoc );

      writeLoc = ( writeLoc + 1 ) % 5;

      output.show( "\twrite " + writeLoc +
                     "\tread " + readLoc);
      displayBuffer( output, sharedInt );

      if ( writeLoc == readLoc ) {
         writeable = false;
         output.show( "\nBUFFER FULL" );
      }

      notify();
   }

   public synchronized int getSharedInt()
   {
      int val;

      while ( !readable ) {
         try {
            output.show( " WAITING TO CONSUME" );
            wait();
         }
         catch ( InterruptedException e ) {
            System.err.println( e.toString() );
         }
      }

      writeable = true;
      val = sharedInt[ readLoc ];

      output.show( "\nConsumed " + val +
                     " from cell " + readLoc );

      readLoc = ( readLoc + 1 ) % 5;

      output.show( "\twrite " + writeLoc +
                     "\tread " + readLoc );
      displayBuffer( output, sharedInt );

      if ( readLoc == writeLoc ) {
         readable = false;
         output.show( "\nBUFFER EMPTY" );
      }

      notify();
      return val;
   }

   public void displayBuffer( SharedCell out, int buf[] )
   {
      DecimalFormat formatNumber = new DecimalFormat( " #;-#" );
      output.show( "\tbuffer: " );

      for ( int i = 0; i < buf.length; i++ )
         output.show( " " + formatNumber.format( buf[ i ] ));
   }
}

Output

Produced 1 into cell 0	write 1	read 0	buffer:   1 -1 -1 -1 -1
Produced 2 into cell 1	write 2	read 0	buffer:   1  2 -1 -1 -1
Produced 3 into cell 2	write 3	read 0	buffer:   1  2  3 -1 -1
Consumed 1 from cell 0	write 3	read 1	buffer:   1  2  3 -1 -1
Produced 4 into cell 3	write 4	read 1	buffer:   1  2  3  4 -1
Produced 5 into cell 4	write 0	read 1	buffer:   1  2  3  4  5
Produced 6 into cell 0	write 1	read 1	buffer:   6  2  3  4  5
BUFFER FULL WAITING TO PRODUCE 7
Consumed 2 from cell 1	write 1	read 2	buffer:   6  2  3  4  5
Produced 7 into cell 1	write 2	read 2	buffer:   6  7  3  4  5
BUFFER FULL WAITING TO PRODUCE 8
Consumed 3 from cell 2	write 2	read 3	buffer:   6  7  3  4  5
Produced 8 into cell 2	write 3	read 3	buffer:   6  7  8  4  5
BUFFER FULL WAITING TO PRODUCE 9
Consumed 4 from cell 3	write 3	read 4	buffer:   6  7  8  4  5
Produced 9 into cell 3	write 4	read 4	buffer:   6  7  8  9  5
BUFFER FULL WAITING TO PRODUCE 10
Consumed 5 from cell 4	write 4	read 0	buffer:   6  7  8  9  5
Produced 10 into cell 4	write 0	read 0	buffer:   6  7  8  9  10
BUFFER FULL
ProduceInteger finished producing values
Terminating ProduceInteger
Consumed 6 from cell 0	write 0	read 1	buffer:   6  7  8  9  10
Consumed 7 from cell 1	write 0	read 2	buffer:   6  7  8  9  10
Consumed 8 from cell 2	write 0	read 3	buffer:   6  7  8  9  10
Consumed 9 from cell 3	write 0	read 4	buffer:   6  7  8  9  10
Consumed 10 from cell 4	write 0	read 0	buffer:   6  7  8  9  10
BUFFER EMPTY
ConsumeInteger retrieved values totaling: 55
Terminating ConsumeInteger


Maintained by John Loomis, last updated 15 July 2000