Tuesday, July 13, 2021

Producer-Consumer Java Program Using wait notify

This Java program solves the Producer-Consumer problem using threads and wait notify. Where one (Producer) thread produces data and another (consumer) thread retrieves it. This program makes use of inter-thread communication using wait, notify, notifyAll.

Producer-Consumer problem

Producer Consumer problem is one of the classic concurrency problem where two processes Producer and Consumer share a common buffer for inserting or retrieving data.

Task of the Producer is to generate data and insert it into the shared buffer.

Task of the Consumer is to consume data from the shared buffer.

Since both of these processes work in tandem and share a buffer so it becomes important to synchronize their access to shared buffer in such a way that the Producer doesn't try to insert data into the buffer when it is full and Consumer doesn't try to consume data from the buffer when it is empty.

Logic for the Producer-Consumer program

There is a shared object, a LinkedList of integers (note that LinkedList class implements Queue interface) which is used by both threads. There is a ProdClass which adds integers to the list and ConClass which retrieves those integers from the list. In the program looping is done for 5 times so there is a condition to break after iteration is done 5 times.

Logic here is that Producer puts one integer in the list and waits until the consumer consumes that integer, that's where wait/notify come into the picture. Producer puts one integer and then go to wait state, while notifying the other thread to wake up and vice versa and this is done with in a synchronized block.

Thus producer and consumer work sequentially where producer adds data and consumer retrieves it and so on.

Producer-Consumer Java program

import java.util.LinkedList;
import java.util.Queue;

public class ProdConDemo {
  public static void main(String[] args) {
    // This is the shared list shared between producer
    // and consumer.. LinkedList implements Queue interface
    Queue<Integer> sharedListObj = new LinkedList<Integer>();
    Thread t1 = new Thread(new ProdClass(sharedListObj), "ProdThread");
    Thread t2 = new Thread(new ConClass(sharedListObj), "ConThread");
    t1.start();
    t2.start(); 
  }
}

// Producer class
class ProdClass implements Runnable{
  Queue<Integer> sharedListObj;
  // Constructor
  ProdClass(Queue<Integer> sharedListObj){
    this.sharedListObj = sharedListObj;
  }
  @Override
  public void run() {
    int i = 0;
    while(true){
      synchronized (sharedListObj) {
        // While condition as mandated to avoid spurious wakeup
        while(sharedListObj.size() >= 1){
          try {
            sharedListObj.wait();
          } catch (InterruptedException e) {
              // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
        // Putting value in the list
        System.out.println("Adding to queue - " + Thread.currentThread().getName() 
           + " " + ++i);
        sharedListObj.add(i);
        sharedListObj.notify();    
        // To get out of while(true) loop (running 5 times only)
        if(i > 4) break;
      }
    }
  }            
}

//Consumer class
class ConClass implements Runnable{
  Queue<Integer> sharedListObj;
  // Constructor
  ConClass(Queue<Integer> sharedListObj){
    this.sharedListObj = sharedListObj;
  }
  @Override
  public void run() {    
    while(true){
      synchronized (sharedListObj) {
        while(sharedListObj.size() < 1){
          try {
            sharedListObj.wait();
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }                    
        }
        int val = sharedListObj.remove();
        // Getting value from the list
        System.out.println("Getting from queue " + Thread.currentThread().getName() 
           + " " + val);
        // To get out of while(true) loop
        if(val == 5) {
          break;
        }
        sharedListObj.notify();        
                
      }
    }
  }
}

Output

Adding to queue - ProdThread 1
Getting from queue ConThread 1
Adding to queue - ProdThread 2
Getting from queue ConThread 2
Adding to queue - ProdThread 3
Getting from queue ConThread 3
Adding to queue - ProdThread 4
Getting from queue ConThread 4
Adding to queue - ProdThread 5
Getting from queue ConThread 5

That's all for this topic Producer-Consumer Java Program Using wait notify. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Print Odd-Even Numbers Using Threads And wait-notify Java Program
  2. How to Create Deadlock in Java
  3. Setting And Getting Thread Name And Thread ID in Java
  4. Why wait(), notify() And notifyAll() Methods Are in Object Class And Not in Thread Class
  5. Synchronization in Java - Synchronized Method And Block

You may also like-

  1. Find Duplicate Characters in a String With Repetition Count Java Program
  2. Find All Permutations of a Given String Java Program
  3. Matrix Multiplication Java Program
  4. How to Read File From The Last Line in Java
  5. How to Inject Prototype Scoped Bean into a Singleton Bean in Spring
  6. Java ThreadLocal Class With Examples
  7. Lambda expression in Java 8
  8. Difference Between ArrayList And CopyOnWriteArrayList in Java