Friday, March 20, 2015

Producer Consumer problem in Java using wait and notify

A classic problem in concurrent programming is the producer-consumer problem. We have a data buffer, one or more producers of data that save it in the buffer and one or more consumers of data that take it from the buffer.
As the buffer is a shared data structure, we have to control the access to it using a synchronization mechanism such as the synchronized keyword, but we have more limitations. A producer can't save data in the buffer if it's full and the consumer can't take data from the buffer if it's empty




For these types of situations, Java provides the wait(), notify(), and notifyAll() methods implemented in the Object class. A thread can call the wait() method inside a synchronized block of code. If it calls the wait() method outside a synchronized block of code, the JVM throws an IllegalMonitorStateException exception. When the thread calls the wait() method, the JVM puts the thread to sleep and releases the object that controls the synchronized block of code that it's executing and allows the other threads to execute other blocks of synchronized code protected by that object. To wake up the thread, you must call the notify() or notifyAll() method inside a block of code protected by the same object.

In this article, you will learn how to implement the producer-consumer problem using the synchronized keyword and the wait(), notify(), and notifyAll() methods

Storage class
It has two attributes: an int attribute called maxSize and a LinkedList<Date> attribute called list.

Implement the synchronized method set() to store an event in the storage. First, check if the storage is full or not. If it's full, it calls the wait() method until the storage has empty space. At the end of the method, we call the notifyAll() method to wake up all the threads that are sleeping in the wait() method.

Implement the synchronized method get() to get an event for the storage. First, check if the storage has events or not. If it has no events, it calls the wait() method until the storage has some events. At the end of the method, we call the notifyAll() method to wake up all the threads that are sleeping in the wait() method.

Producer and Consumer
Create a class named Producer and Consumer and specify that it implements the Runnable interface. 
Main Class
Sample Output


How it works...
The key to this example is the set() and get() methods of the EventStorage class. First of all, the set() method checks if there is free space in the storage attribute. If it's full, it calls the wait() method to wait for free space. When the other thread calls the notifyAll() method, the thread wakes up and checks the condition again. The notifyAll() method doesn't guarantee that the thread will wake up. This process is repeated until there is free space in the storage and it can generate a new event and store it.

The behavior of the get() method is similar. First, it checks if there are events on the storage. If the EventStorage class is empty, it calls the wait() method to wait for events. Where the other thread calls the notifyAll() method, the thread wakes up and checks the condition again until there are some events in the storage.

If you run this example, you will see how producer and consumer are setting and getting the events, but the storage never has more than 10 events.




If you know anyone who has started learning java, why not help them out! Just share this post with them. Thanks for studying today!...

1 comment: