user10675448
user10675448

Reputation: 33

Producer Consumer using wait and notify : Consumer does not receive messages

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

Answers (2)

Chetan Kinger
Chetan Kinger

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

Sarjit
Sarjit

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

Related Questions