mercury0114
mercury0114

Reputation: 1449

Java Producer-Consumer: producer does not "notify()" the consumer

I am trying to implement a producer - consumer problem with one producer and one consumer. The producer can not create more than five products. The consumer can not consume a product if there is no.

I am locking them both on a field called "monitor", when needed.

Here is my code:

import java.util.concurrent.TimeUnit;

public class ConsumerProducer {

private static final Object monitor = new Object();
private final int MAX_PRODUCTS = 5;
private String[] products = new String[MAX_PRODUCTS];

int slotToProduce = 0;
int slotToConsume = 0;

private Thread producer = new Thread(new Producer());
private Thread consumer = new Thread(new Consumer());

class Producer implements Runnable {

    private synchronized void produce() {
        synchronized (monitor) {
            // Acquiring access to produce a product
            while (slotToProduce - slotToConsume == MAX_PRODUCTS) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                }
            }

            // Producing a product
            System.out.println("Will now produce product " + slotToProduce);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
            }
            products[slotToProduce % MAX_PRODUCTS] = "Teddy Bear "
                    + Integer.toString(slotToProduce);
            System.out.println("Successfully produced product "
                    + products[slotToProduce % MAX_PRODUCTS]);
            slotToProduce++;

            // Notifying consumers if there were no products before
            if (slotToProduce - slotToConsume == 1) {
                notify();
            }
        }
    }

    @Override
    public void run() {
        while (true) {
            produce();
        }
    }

}

class Consumer implements Runnable {

    private synchronized void consume() {
        synchronized (monitor) {
            // Acquiring access to consume a product
            while (slotToProduce == slotToConsume) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                }
            }

            // Consuming a product
            System.out.println("Will now consume product "
                    + products[slotToConsume % MAX_PRODUCTS]);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
            }
            System.out.println("Successfully consumed product "
                    + products[slotToConsume % MAX_PRODUCTS]);
            slotToConsume++;

            // Notifying producers if before there were no spaces to produce
            // a product
            if (slotToProduce - slotToConsume == MAX_PRODUCTS - 1) {
                notify();
            }
        }
    }

    @Override
    public void run() {
        while (true) {
            consume();
        }
    }
}

public static void main(String args[]) {
    final ConsumerProducer cp = new ConsumerProducer();
    cp.producer.start();
    cp.consumer.start();
}

}

However, when I run my program, the output is:

and from here on the program halts.

So the question is: even if I synchronize both consumer and producer on the same object "monitor", why the consumer stays asleep all the time?

Upvotes: 0

Views: 94

Answers (1)

Natalia
Natalia

Reputation: 4532

You are synchonizing on monitor object. But you invoke sleep and notify on the producer and consumer object.

required changes:

  1. invoke wait(), notify() on monitor
  2. remove synchonized on methods. Leave only sync on monitor object.
  3. never ignore interrupted exceptions!
  4. think about using queue. Look at interface java.util.concurrent.BlockingQueue

Upvotes: 3

Related Questions