Search code examples
javamultithreadingproducer-consumer

Producer-Consumer example not working


Can someone please help me fix this program. I have created one producer class that asks for the input using the Scanner class, Next I have created a class Consumer where I have used those inputs of length and width to calculate the Area. Finally, I have created a class with the main method to start both the producer and consumer Threads.

PRODUCER:-

package Test1;
import java.util.*;
public class Producer extends Thread
{
   public int length;
   public int width;
   Scanner scan=new Scanner(System.in);

   public void run()
   {
       while(true)
       {
           synchronized(this)
           {
               length=scan.nextInt();
               width=scan.nextInt();
               this.notify();
           }
       }
   }

}

CONSUMER:-

package Test1;

public class Consumer extends Thread 
{
    Producer producer;
    Consumer(Producer producer)
    {
        this.producer=producer;
    }
  public void run()
  {
      while(true)
      {
          synchronized(producer)
          {
              try 
              {
                  System.out.println("Waiting for values from the Producer");
                  producer.wait();
              }
              catch(InterruptedException e)
              {
                  e.printStackTrace();
              }

             int area= calculateArea();
             System.out.println("Area is "+area);

          }
      }
  }
  public int calculateArea()
  {
      return producer.length *producer.width;
  }
}

MAIN CLASS:-

package Test1;

public class UsingPandC extends Thread {

    public static void main(String[] args) 
    {
        Producer producer=new Producer();
        Consumer consumer=new Consumer(producer);
        producer.start();
        consumer.start();

    }

}

I was expecting the console to ask me for inputs(which it does), next I was expecting it to Notify the Thread waiting for the lock to be released on the consumer class(Which I think does not happen) and then I was expecting it to calculate the area and put the Consumer back to the wait state(which also does not happen and ask for more inputs.


Solution

  • synchronize(...) marks a critical section where only one thread is ever allowed to execute the code block. Although you notify the consumer thread to wake up, your producer thread almost instantly reclaims the intrinsic lock of its class and requests the next input as it does not have to wait on anything other or has to execute code outside of the critical section which needs a couple of CPU cycles. Switching the context of threads may take a little while as it is not that cheap. This overhead is thoug enough that the producer thread can enter the critical section again in the next iteration of the loop and therefore reclaim exclusive rights to execute its code, which just waits on user input. The consumer thread on the other side notices after getting activated that an other thread (the producer thread) gained the intrinsic lock of the critical section and goes suspended again.

    If you limit the syncronization block in the producer to the notification only and exclude the input handling from the critical section your sample should work as intended as now the producer needs plenty more CPU cycles to reach the synchronization block again and threfore allows the consumer thread to actually acquire the intrinsic lock and perform its task.