Producer-consumer Problem is one of the classic problems of multi-threading and also frequently asked in some of the interviews along with Print Odd Even Numbers Using two threads and Print 1,2,3 Using 3 Threads.
In this blog, I will explain how to write a java program using inter-thread communication. In short using wait() and notify() methods.
Problem Statement
There is one queue of n capacity. This queue is shared between producer and
consumer. n is the capacity and for this blog, I will take n = 5.
Producer adds a block to the queue when queue size is less than its capacity.
Consumer will consume from the same queue when queue size is greater than 0.
Using multi-threading, we need to write java program with thread
synchronization.
Approach
If you have gone through earlier blogs to Print Odd Even Numbers Using two threads and Print 1,2,3 Using 3 Threads , you will notice a pattern which can be applied here as well. Take
sometime to understand the pattern.
Let us create two threads initially denoting producer and consumer. You can
take the capacity from program arguments. I hardcoded this value to 5.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Control { | |
public static void main(String[] args) { | |
ProducerConsumer producerConsumer = new ProducerConsumer(5); | |
Thread producer = new Thread(new Task(true, producerConsumer), "Producer "); | |
Thread consumer = new Thread(new Task(false, producerConsumer), "Consumer "); | |
producer.start(); | |
consumer.start(); | |
} | |
} |
When the queue is empty(), we need to produce to it. Here, producer will
get a head start as queue is empty and consumer will be waiting for its turn
till producer finishes producing to the queue.
Once producer finishes, consumer will start consuming and producer will be
waiting till the queue is emptied. This will go on based on the condition in
the while loop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Task implements Runnable { | |
boolean isProducer; | |
ProducerConsumer producerConsumer; | |
public Task(boolean isProducer, ProducerConsumer producerConsumer) { | |
this.isProducer = isProducer; | |
this.producerConsumer = producerConsumer; | |
} | |
@Override | |
public void run() { | |
try { | |
while (true) { | |
if (isProducer) { | |
producerConsumer.produce(); | |
} else { | |
producerConsumer.consume(); | |
} | |
} | |
} catch (InterruptedException e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
Here, the producer thread will only execute produce() method and consumer will
only execute consumer() method of ProducerConsumer Object.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ProducerConsumer { | |
Queue<Integer> list; | |
int capacity; | |
volatile int value = 1; | |
public ProducerConsumer(int capacity) { | |
this.capacity = capacity; | |
list = new LinkedList<>(); | |
} | |
public synchronized void produce() throws InterruptedException { | |
while (capacity == list.size()) { | |
wait(); | |
} | |
System.out.println(Thread.currentThread().getName() + "Produced : " + value); | |
list.add(value++); | |
notify(); | |
Thread.sleep(1000); | |
} | |
public synchronized void consume() throws InterruptedException { | |
while (0 == list.size()) { | |
wait(); | |
} | |
System.out.println(Thread.currentThread().getName() + "Consumed : " + list.poll()); | |
value--; | |
notify(); | |
Thread.sleep(1000); | |
} | |
} |
Feel free to experiment as there are lot of versions of this problem. Try it
out with multiple consumers and experiment with waiting logic.
Post a Comment