Skip to main content

Producer Consumer Design Pattern By using wait(), notify() and notifyAll() methods

Producer Consumer Problem is a classical concurrency problem. In fact it is one of the concurrency design pattern.  

Producer Consumer Design Patter can either be implemented using following two approaces.

  1. By using wait(), notify() and notifyAll() methods
  2. By using BlockingQueue 


In this post I will explain implementation using wait() and notify() method. If you are interested in the implementation using Blocking Queue, you can check my post Producer Consumer Design Pattern using BlockingQueue.



The Object class in java contains three final methods that allows threads to communicate about the lock status of a resource. These methods are wait(), notify() and notifyAll()

We can use wait() method to pause execution of thread.

notify() and notifyAll() methods are used to wake up waiting thread.  Both notify() and notifyAll() method sends a notification but notify() sends the notification to only one of the waiting thread, no guarantee which thread will receive notification and notifyAll() sends the notification to all threads.

So if only one thread is waiting for an object lock, also known as a monitor then both notify and notifyAll will send the notification to it. If multiple threads are waiting on a monitor then notify will only inform one of the lucky thread and rest will not receive any notification, but notifyAll will inform all threads.

Understanding Java Program

In this program, we have two threads named PRODUCER and CONSUMER, which are  instance of Producer and Consumer class respectively.  Both of these class implements Runnable interface.

The logic of what producer and the consumer should do is written in their respective run() method.

Main thread starts both PRODUCER and CONSUMER threads and also create an object of LinkedList class i.e. sharedQ to share as Queue between them.

maximum size of sharedQ is defined using maxSize variable.
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
 
 
/**
 * Simple Java Program to test Producer Consumer Design Pattern
 * using  wait, notify and notifyAll() methods
 *
 *
 */
public class ProducerConsumerTest {
 
    public static void main(String[] args) throws InterruptedException {
         
         
        final Queue sharedQ = new LinkedList < Integer >();
         
        Thread consumerThread = new Thread(new Consumer(sharedQ, 4), "CONSUMER");
        Thread producerThread = new Thread(new Producer(sharedQ, 4), "PRODUCER");
         
        producerThread.start();
        consumerThread.start();
         
         
    }
 
}


Producer runs in an infinite loop and keeps inserting random integer value from 1 to 100 into sharedQ until the queue is full.

We use condition while(queue.size == maxSize) to confirm if queue is full or not. This condition is a part of synchronized block on shareQ object, so that no other thread can modify the queue while executing this line of code.

If sharedQ is full then our PRODUCER thread waits until CONSUMER thread consumes one item and makes space in queue.

It calls notify() method to inform PRODUCER thread. 

Both wait() and notify() methods are called on shared object which is sharedQ in our case.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
 * Producer Thread will keep producing values for Consumer.
 *
 * It will use wait() method when Queue is full and
 * use notify() method to send notification to Consumer Thread.
 *
 *
 */
class Producer implements Runnable
{
    private final Queue sharedQ;
    private int maxSize;
     
    public Producer(Queue sharedQ, int maxSize)
    {
        this.sharedQ = sharedQ;
        this.maxSize = maxSize;
    }
     
    @Override
    public void run(){
         
        while(true)
        {
            synchronized (sharedQ) {
                while(sharedQ.size()==maxSize)
                {
                    try
                    {
                        System.out.println("Queue is full");
                        sharedQ.wait();
                    }
                    catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                     
                }
                Random random = new Random();
                int number = random.nextInt(100);
                System.out.println("Producing value " + number);
                sharedQ.add(number);
                sharedQ.notify();
                 
            }
             
        }
    }
}

Similarly Consumer runs in an infinite loop and keeps consuming integers from sharedQ until the queue is empty. It uses while(sharedQ.isEmpty()) condition to keep checking if sharedQ is empty or not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 * Consumer Thread will consumer values form shared queue.
 *
 * It will use wait() method to wait if queue is empty.
 *
 * It will also use notify method to send notification
 * to producer thread after consuming values from queue.
 *
 *
 */
class Consumer implements Runnable
{
    private final Queue sharedQ;
    private int maxSize;
     
    public Consumer(Queue sharedQ, int maxSize)
    {
        this.sharedQ = sharedQ;
        this.maxSize = maxSize;
    }
     
    @Override
    public void run(){
        while(true)
        {
            synchronized (sharedQ) {
                while(sharedQ.isEmpty())
                {
                    try {
                        System.out.println("Que is Empty");
                        sharedQ.wait();
                    }
                    catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
                 
                int number = (int) sharedQ.poll();
                System.out.println("removing Element " + number);
                sharedQ.notify();
                 
            }
        }
    }
     
}

Download Complete Java Program »

Comments

Popular posts from this blog

Yahoo! Calendar "Add Event" Seed URL Parameters

I can't seem to find any official documentation on this, so here are my notes. Some information gathered from  http://richmarr.wordpress.com/tag/calendar/ Other information gathered through trial and error, and close examination of the "Add Event" form on Yahoo!'s site. Yahoo! Calendar URL Parameters Parameter Required Example Value Notes v Required 60 Must be  60 . Possibly a version number? TITLE Required Event title Line feeds will appear in the confirmation screen, but will not be saved. May not contain HTML. ST Required 20090514T180000Z Event start time in UTC. Will be converted to the user's time zone. 20090514T180000 Event start time in user's local time 20090514 Event start time for an all day event. DUR value is ignored if this form is used. DUR 0200 Duration of the event. Format is HHMM, zero-padded. MM may range up to 99, and is converted into hours appropriately. HH values over 24 hours appear to be modulated by 24. Durations t...

Java literals:

Java literals:           A constant value which can be assigned to a variable is known as Literal.If we are assigning any outside range value for any data type ,we will get a compile time error saying Possible Loss of Precision found int required byte. For the integral data types (int ,byte,short,long) : we are allowed to specify a literal value in any   one of the following three forms. ---> Decimal literal (normal way) --->Octa literal (prefixed with 0 ) --->Hexa decimal (prefixed with 0x ) int x=10 ------------> Decimal int x=010 ------------>Octa int x=0X10 -------------->Hexa In the Hexa decimal notation for the extra digits we are allowed to specify either small or upper case a,b,c or A,B,C ( this is one of the few places where java is not case sensitive ). Example: class Sample { public static void main(String add[]) { int i = 10; int j=010; int k=0x10; System.out.println( i+”….”+j...