Two threads correctly manipulating a synchronized buffer. - Java Thread

Java examples for Thread:Producer Consumer

Description

Two threads correctly manipulating a synchronized buffer.

Demo Code

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import java.security.SecureRandom;

class Consumer implements Runnable
{ 
   private static final SecureRandom generator = new SecureRandom();
   private final Buffer sharedLocation; // reference to shared object

   public Consumer(Buffer sharedLocation)
   {//from  w  ww  . j av  a  2s.c o  m
      this.sharedLocation = sharedLocation;
   }
   // read sharedLocation's value 10 times and sum the values
   public void run()                                           
   {
      int sum = 0;

      for (int count = 1; count <= 10; count++) 
      {
         // sleep 0 to 3 seconds, read value from buffer and add to sum
         try 
         {
            Thread.sleep(generator.nextInt(3000));
            sum += sharedLocation.blockingGet();
         } 
         catch (InterruptedException exception) 
         {
            Thread.currentThread().interrupt(); 
         } 
      } 

      System.out.printf("%n%s %d%n%s%n", 
         "Consumer read values totaling", sum, "Terminating Consumer");
   } 
}
interface Buffer
{
   public void blockingPut(int value) throws InterruptedException; 
   public int blockingGet() throws InterruptedException; 
}
class SynchronizedBuffer implements Buffer
{
   private int buffer = -1; // shared by producer and consumer threads
   private boolean occupied = false;

   public synchronized void blockingPut(int value) 
      throws InterruptedException
   {
      // while there are no empty locations, place thread in waiting state
      while (occupied) 
      {
         System.out.println("Producer tries to write."); // for demo only
         displayState("Buffer full. Producer waits."); // for demo only
         wait();
      }
        
      buffer = value; // set new buffer value
      occupied = true;
      displayState("Producer writes " + buffer); // for demo only
      notifyAll(); // tell waiting thread(s) to enter runnable state
   } 
   public synchronized int blockingGet() throws InterruptedException
   {
      while (!occupied)
      {
         System.out.println("Consumer tries to read."); // for demo only
         displayState("Buffer empty. Consumer waits."); // for demo only
         wait();
      }
      occupied = false;
      displayState("Consumer reads " + buffer); // for demo only
      notifyAll(); // tell waiting thread(s) to enter runnable state
      return buffer;
   } 
   private synchronized void displayState(String operation)
   {
      System.out.printf("%-40s%d\t\t%b%n%n", operation, buffer, 
         occupied);
   } 
}
class Producer implements Runnable
{
   private static final SecureRandom generator = new SecureRandom();
   private final Buffer sharedLocation; // reference to shared object

   public Producer(Buffer sharedLocation)
   {
      this.sharedLocation = sharedLocation;
   } 

   // store values from 1 to 10 in sharedLocation
   public void run()                             
   {
      int sum = 0;

      for (int count = 1; count <= 10; count++)
      {
         try // sleep 0 to 3 seconds, then place value in Buffer
         {
            Thread.sleep(generator.nextInt(3000)); // random sleep
            sharedLocation.blockingPut(count); // set value in buffer
            sum += count; // increment sum of values
         } 
         catch (InterruptedException exception) 
         {
            Thread.currentThread().interrupt(); 
         } 
      } 

      System.out.printf(
         "Producer done producing%nTerminating Producer%n");
   } 
}

public class Main
{
   public static void main(String[] args) throws InterruptedException
   {
      ExecutorService executorService = Executors.newCachedThreadPool();
      Buffer sharedLocation = new SynchronizedBuffer();

      System.out.printf("%-40s%s\t\t%s%n%-40s%s%n%n", "Operation", 
         "Buffer", "Occupied", "---------", "------\t\t--------");

      executorService.execute(new Producer(sharedLocation));
      executorService.execute(new Consumer(sharedLocation));

      executorService.shutdown();
      executorService.awaitTermination(1, TimeUnit.MINUTES); 
   }
}

Result


Related Tutorials