Here come the time to answer very very important question from interview perspective. Interviewers tends to check how sound you are in threads inter communication. Because for solving this problem we got to use synchronization blocks, wait() and notify() method very cautiously. If you misplace synchronization block or any of the method, that may cause your program to go horribly wrong. So, before going into this question first i’ll recommend you to understand how to use synchronized blocks, wait() and notify() methods.
Earlier we read about Solve Consumer Producer problem by using wait() and notify() methods in multithreading in java,
Logic is explained in comments in program
Full Program/sourceCode to How to solve MULTIPLE producer consumer and producer problem using wait() and notify() method>
import java.util.LinkedList;
import java.util.List;
/**
* Producer Class.
*/
class Producer implements Runnable {
private List<Integer> sharedQueue;
private int maxSize=4; //maximum number of products which sharedQueue can hold at a time.
int productionSize=5; //Total no of items to be produced by each producer
int producerNo;
public Producer(List<Integer> sharedQueue, int producerNo) {
this.sharedQueue = sharedQueue;
this.producerNo = producerNo;
}
@Override
public void run() {
for (int i = 1; i <= productionSize; i++) { //produce products.
try {
produce(i);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
private void produce(int i) throws InterruptedException {
synchronized (sharedQueue) {
//if sharedQuey is full wait until consumer consumes.
while (sharedQueue.size() == maxSize) {
System.out.println(Thread.currentThread().getName()+", Queue is full, producerThread is waiting for "
+ "consumerThread to consume, sharedQueue's size= "+maxSize);
sharedQueue.wait();
}
//Bcz each producer must produce unique product
//Ex= producer0 will produce 1-5 and producer1 will produce 6-10 in random order
int producedItem = (productionSize*producerNo)+ i;
System.out.println(Thread.currentThread().getName() +" Produced : " + producedItem);
sharedQueue.add(producedItem);
Thread.sleep((long)(Math.random() * 1000));
sharedQueue.notify();
}
}
}
/**
* Consumer Class.
*/
class Consumer implements Runnable {
private List<Integer> sharedQueue;
public Consumer(List<Integer> sharedQueue) {
this.sharedQueue = sharedQueue;
}
@Override
public void run() {
while (true) {
try {
consume();
Thread.sleep(100);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
private void consume() throws InterruptedException {
synchronized (sharedQueue) {
//if sharedQuey is empty wait until producer produces.
while (sharedQueue.size() == 0) {
System.out.println(Thread.currentThread().getName()+", Queue is empty, consumerThread is waiting for "
+ "producerThread to produce, sharedQueue's size= 0");
sharedQueue.wait();
}
Thread.sleep((long)(Math.random() * 2000));
System.out.println(Thread.currentThread().getName()+", CONSUMED : "+ sharedQueue.remove(0));
sharedQueue.notify();
}
}
}
public class MULTIPLE_ProducerConsumerWaitNotify {
public static void main(String args[]) {
List<Integer> sharedQueue = new LinkedList<Integer>(); //Creating shared object
Producer producer0=new Producer(sharedQueue, 0);
Consumer consumer0=new Consumer(sharedQueue);
Thread producerThread0 = new Thread(producer0, "ProducerThread0");
Thread consumerThread0 = new Thread(consumer0, "ConsumerThread0");
producerThread0.start();
consumerThread0.start();
System.out.println("MID");
Producer producer1=new Producer(sharedQueue, 1);
Consumer consumer1=new Consumer(sharedQueue);
Thread producerThread1 = new Thread(producer1, "ProducerThread1");
Thread consumerThread1 = new Thread(consumer1, "ConsumerThread1");
producerThread1.start();
consumerThread1.start();
}
}
/*OUTPUT
MID
ProducerThread0 Produced : 1
ProducerThread0 Produced : 2
ConsumerThread1, CONSUMED : 1
ProducerThread1 Produced : 6
ProducerThread1 Produced : 7
ProducerThread1 Produced : 8
ProducerThread1, Queue is full, producerThread is waiting for consumerThread to consume, sharedQueue's size= 4
ConsumerThread0, CONSUMED : 2
ProducerThread1 Produced : 9
ProducerThread1, Queue is full, producerThread is waiting for consumerThread to consume, sharedQueue's size= 4
ConsumerThread0, CONSUMED : 6
ConsumerThread1, CONSUMED : 7
ProducerThread0 Produced : 3
ProducerThread0 Produced : 4
ProducerThread0, Queue is full, producerThread is waiting for consumerThread to consume, sharedQueue's size= 4
ConsumerThread1, CONSUMED : 8
ConsumerThread0, CONSUMED : 9
ProducerThread1 Produced : 10
ConsumerThread0, CONSUMED : 3
ConsumerThread1, CONSUMED : 4
ProducerThread0 Produced : 5
ConsumerThread1, CONSUMED : 10
ConsumerThread0, CONSUMED : 5
ConsumerThread1, Queue is empty, consumerThread is waiting for producerThread to produce, sharedQueue's size= 0
ConsumerThread0, Queue is empty, consumerThread is waiting for producerThread to produce, sharedQueue's size= 0
*/
|
RELATED LINKS>
Consumer Producer problem solution using different techniques >
Solve Consumer Producer problem by using wait() and notify() methods in multithreading
solve Consumer Producer problem by using wait() and notify() methods, where consumer can consume only when production is over
How to solve Consumer Producer problem without using wait() and notify() methods, where consumer can consume only when production is over.
BlockingQueue >
Solve Consumer Producer problem by using BlockingQueue in multithreading
Custom implementation of LinkedBlockingQueue class which implements BlockingQueue interface
Interviews >