Reputation: 33
I have prepared a producer consumer using wait and notify mechanism in Java. Below is the code:
class Producer implements Runnable {
private int i = 0;
private ArrayList<Integer> arrayList;
private static final int MAX_SIZE = 5;
public Producer(ArrayList<Integer> arrayList) {
this.arrayList = arrayList;
}
@Override
public void run() {
while(true) {
try {
produce(i++);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private synchronized void produce(int i) throws InterruptedException {
while(arrayList.size() == MAX_SIZE) {
System.out.println("The Queue is Full. Producer thread needs to wait.");
wait();
}
arrayList.add(i);
System.out.println("Added Element: "+i);
notifyAll();
Thread.sleep(3000);
}
}
class Consumer implements Runnable {
private ArrayList<Integer> arrayList;
public Consumer(ArrayList<Integer> arrayList) {
this.arrayList = arrayList;
}
@Override
public void run() {
while(true) {
try {
consume();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private synchronized void consume() throws InterruptedException {
while(arrayList.isEmpty()) {
System.out.println("The Queue is empty. Consumer thread needs to wait.");
wait();
}
int data = arrayList.remove(0);
System.out.println("Removed Element: "+data);
notifyAll();
Thread.sleep(3000);
}
}
public class ProducerConsumerExample {
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
Thread producer = new Thread(new Producer(arrayList), "Producer Thread");
Thread consumer = new Thread(new Consumer(arrayList), "Consumer Thread");
producer.start();
consumer.start();
}
}
Below is the sample output
The Queue is empty. Consumer thread needs to wait.
Added Element: 0
Added Element: 1
Added Element: 2
Added Element: 3
Added Element: 4
The Queue is Full. Producer thread needs to wait.
The issue is that the consumer thread is either not getting the notification or the notification is getting lost. I have tried understanding the code but not getting any clue as to where I am going wrong.
Upvotes: 1
Views: 651
Reputation: 15212
The issue is that the consumer thread is either not getting the notification or the notification is getting lost
The reason why this happens is that the Producer
and the Consumer
are not Synchronizing on the same instance. They are independently Synchronizing on their own instance (i.e this
). To fix this, both the Producer
and the Consumer
can Synchronize on the instance of the ArrayList
or another shared object.
Upvotes: 2
Reputation: 809
Producer and Consumer are synchronized on this of its own instance.But it should be synchronized on common object and same object we have to call wait and notify. I have modified your code to work accordingly.Please check
import java.util.ArrayList;
class Producer implements Runnable {
private ArrayList<Integer> arrayList;
private static final int MAX_SIZE = 5;
public Producer(ArrayList<Integer> arrayList) {
this.arrayList = arrayList;
}
@Override
public void run() {
while(true) {
try {
produce();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void produce() throws InterruptedException {
synchronized (arrayList) {
while (arrayList.size() == MAX_SIZE) {
System.out.println("The Queue is Full. Producer thread needs to wait.");
arrayList.wait();
}
System.out.println("Added Element: " + ProducerConsumerExample.i);
arrayList.add(ProducerConsumerExample.i++);
arrayList.notify();
Thread.sleep(3000);
}
}
}
class Consumer implements Runnable {
private ArrayList<Integer> arrayList;
public Consumer(ArrayList<Integer> arrayList) {
this.arrayList = arrayList;
}
@Override
public void run() {
while(true) {
try {
consume();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void consume() throws InterruptedException {
synchronized (arrayList) {
while (arrayList.isEmpty()) {
System.out.println("The Queue is empty. Consumer thread needs to wait.");
arrayList.wait();
}
int data = arrayList.remove(--ProducerConsumerExample.i);
System.out.println("Removed Element: " + data);
arrayList.notify();
Thread.sleep(3000);
}
}
}
public class ProducerConsumerExample {
static int i = 0;
public static void main(String[] args) {
ArrayList<Integer> arrayList = new ArrayList<Integer>();
Thread producer = new Thread(new Producer(arrayList), "Producer Thread");
Thread consumer = new Thread(new Consumer(arrayList), "Consumer Thread");
producer.start();
consumer.start();
}
}
Output : -
Added Element: 0
Added Element: 1
Added Element: 2
Added Element: 3
Added Element: 4
The Queue is Full. Producer thread needs to wait.
Removed Element: 4
Removed Element: 3
Removed Element: 2
Removed Element: 1
Removed Element: 0
The Queue is empty. Consumer thread needs to wait.
Added Element: 0
Added Element: 1
Added Element: 2
Added Element: 3
Added Element: 4
The Queue is Full. Producer thread needs to wait.
Removed Element: 4
Removed Element: 3
Note :- Need not to wait till Arraylist reached max size,try to consume it once it was produce by producer.
Upvotes: 0