Skip to main content

Implementing the Producer Consumer Pattern Using Wait and Notify in Java

Below are the conditions for producer consumer pattern. We need to ensure that the thread should not be blocked either if the buffer is empty or full. This is achieved by calling wait() and notify() method on the lock object which is used to synchronized the block of code. Please note that it is important for both threads to synchronize on the same monitor / lock object.
  • A producer produces values inside a buffer.
  • A consumer consumes the values from this buffer.
  • The buffer can be empty or full.
  • Producer and consumer runs in their own thread.

Note: wait() and notify() should not be called outside the synchronized code block

Below is the example code :

package com.refermynotes;

public class ProducerConsumerExample {
public static int[] buffer;
public static Object lock = new Object();
public static int count;

static class Producer{
public void produce(){
synchronized (lock) {
if(isFull(buffer)){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Produced: "+count);
buffer[count++] = 1;
lock.notifyAll();
}
}
}

static class Consumer{
public void consume(){
synchronized(lock){
if(isEmpty()){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buffer[--count] = 0;
System.out.println("Consumed: "+count);
lock.notifyAll();
}
}
}

private static boolean isEmpty() {
return count == 0;
}
private static boolean isFull(int[] buffer) {
return count == buffer.length;
}

public static void main(String[] args) {
buffer = new int[50];
count = 0;
final Producer p = new Producer();
final Consumer c = new Consumer();

Runnable producerTask = new Runnable() {
@Override
public void run() {
for(int i =0; i<100 font="" i="">
p.produce();
}
System.out.println("Done Producing");
}
};

Runnable consumerTask = new Runnable() {
@Override
public void run() {
for(int i =0; i<100 font="" i="">
c.consume();
}
System.out.println("Done Consuming");
}
};

Thread producerThread = new Thread(producerTask);
Thread consumerThread = new Thread(consumerTask);

producerThread.start();
consumerThread.start();

try {
producerThread.join();
consumerThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("Remaining :"+count);

}
}

Comments

Popular posts from this blog

Job Sequencing with Deadlines

Given a set of n jobs Each job i has an integer deadlines di>=0 and a profit pi>0 All jobs requires only one unit time to complete Only one machine is available for processing jobs For job i the profit pi is earned if the job is completed by its deadline.

Optimal Binary Search using Dynamic Programming

An optimal binary search tree is a binary search tree for which the nodes are arranged on levels such that the tree cost is minimum. If the probabilities of searching for elements of a set are known from accumulated data from past searches, then Binary Search Tree (BST) should be such that the average number of comparisons in a search should be minimum. eg. Lets the elements to be searched are A, B, C, D and probabilities of searching these items are 0.1, 0.2, 0.4 and 0.3 respectively. Lets consider 2 out of 14 possible BST containing these keys. Figure 1 Figure 2 Average number of comparison is calculated as sum of level*probability(key element) for each element of the tree. Lets the level of tree start from 1. Therefore, for figure 1 -     Average number of comparison = 1*0.1 +2*0.2 +3*0.4 +4*0.3  = 2.9                                  ...

Travel Sales Man Problem (TSP) and Solution using Dynamic Programming

Given a graph of n vertices, determine the minimum cost path to start at a given vertex and travel to each other vertex exactly once, returning to the starting vertex. In some versions, the starting and ending points are different and fixed, and all other points have to be visited exactly once from start to end. A standard way to solve these problems is to try all possible orders of visiting the n points, which results in a run-time of O(n!). To calculate cost using Dynamic Programming, we need to establish recursive relation in terms of sub-problems. Let us define a term C(S, i) be the cost of the minimum cost path visiting each vertex in set S exactly once, starting at 1 and ending at i. We start with all subsets of size 2 and calculate C(S, i) for all subsets where S is the subset, then we calculate C(S, i) for all subsets S of size 3 and so on. Note that 1 must be present in every subset. So the algorithm is like below - If size of S is 2, then S must be {1, i},  C(S, ...