Thursday, 10 August 2017

Producer Consumer Problem - Solution using wait and notify In Java

        This is very important question for the experienced interview perspective. This question will ask mostly 4+ years of experienced peoples. In this problem, again two approaches first one using wait and notify another one using BlockingQueue . In this post, we can discuss or solution using wait and notify.
        Before going through solution,  first need to understand the synchronized block and methods. In this producer and consumer problem solution, we are using synchronization concept.

Below example,
       --->  Producer will produce total of 10 products and can not produce more than 1 item at a time until products are being consumed by the consumer
In code, when sharedQueue size is 1, wait for producer till consumer consume the product.

     ---> Consumer can consume products only when products are available.
In code, when sharedQueue size is 0, wait for consumer till producer produce the product.

Program to Solve the Producer-Consumer Problem using wait and notify


  package com.pr;  
  import java.util.ArrayList;  
  import java.util.List;  
  public class ProducerConsumer {  
       public static void main (String[] args) {  
            List<Integer> sharedQueue = new ArrayList<Integer>();  
            Producer producer = new Producer(sharedQueue);  
            Consumer consumer = new Consumer(sharedQueue);  
            Thread p = new Thread(producer, "Producer Thread");  
            Thread c = new Thread(consumer, "Consumer Thread");  
            p.start();  
            c.start();  
       }  
  }  
  class Producer implements Runnable {  
       List<Integer> sharedQueue = new ArrayList<Integer>();  
       public Producer(List<Integer> sharedQueue) {  
            this.sharedQueue = sharedQueue;  
       }  
       public void run() {  
            for (int i = 1; i<=10; i++) {  
                 try {  
                      produce(i);  
                 } catch(InterruptedException e) {  
                      e.printStackTrace();  
                 }  
            }  
       }  
       private void produce(int i) throws InterruptedException{  
            synchronized (sharedQueue) {  
                 if (sharedQueue.size() == 1) {  
                      System.out.println("Queue is full");  
                      sharedQueue.wait();  
                 }  
            }  
            synchronized (sharedQueue) {  
                 System.out.println("Produced : "+i);  
                 sharedQueue.add(i);  
                 Thread.sleep(1000);  
                 sharedQueue.notify();  
            }  
       }  
  }  
  class Consumer implements Runnable {  
       List<Integer> sharedQueue = new ArrayList<Integer>();  
       public Consumer(List<Integer> sharedQueue) {  
            this.sharedQueue = sharedQueue;  
       }  
       @Override  
       public void run() {  
            while (true) {  
                 try {  
                      consume();  
                      Thread.sleep(1000);  
                 } catch(InterruptedException e) {  
                      e.printStackTrace();  
                 }  
            }  
       }       
       private void consume() throws InterruptedException{  
            synchronized (sharedQueue) {  
                 while (sharedQueue.size() == 0) {  
                      System.out.println("Queue is empty");  
                      sharedQueue.wait();  
                 }  
            }  
            synchronized (sharedQueue) {  
                 Thread.sleep(1000);  
                 System.out.println("Consumed :" +sharedQueue.remove(0));  
                 sharedQueue.notify();  
            }  
       }  
  }   

Output : - Produced : 1
 Queue is full
 Consumed : 1
 Produced : 2
 Queue is full
 Consumed : 2
 Produced : 3
 Queue is full
 Consumed : 3
 Produced : 4
 Queue is full
 Consumed : 4
 Produced : 5
 Consumed : 5
 Produced : 6
 Queue is full
 Consumed : 6
 Produced : 7
 Consumed : 7
 Produced : 8
 Consumed : 8
 Produced : 9
 Queue is full
 Consumed : 9
 Produced : 10
 Consumed : 10
 Queue is empty 

Another way solving the producer consumer problem is using BlockingQueue.  BlockingQueue can reduce the code complexity no need to write wait and notify.  In next post we can discuss about BlockingQueue.