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.
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.
|
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.
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();
}
}
}
}