w3resource

Java Program with wait() and notify() for Thread Synchronization

Java Multithreading: Exercise-2 with Solution

Write a Java program to create a producer-consumer scenario using the wait() and notify() methods for thread synchronization.

Sample Solution-1:

Java Code:

// ProducerConsumer.java
import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumer {
  private static final int BUFFER_SIZE = 5;
  private static final Queue < Integer > buffer = new LinkedList < > ();

  public static void main(String[] args) {
    Thread producerThread = new Thread(new Producer());
    Thread consumerThread = new Thread(new Consumer());

    producerThread.start();
    consumerThread.start();
  }

  static class Producer implements Runnable {
    public void run() {
      int value = 0;
      while (true) {
        synchronized(buffer) {
          // Wait if the buffer is full
          while (buffer.size() == BUFFER_SIZE) {
            try {
              buffer.wait();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }

          System.out.println("Producer produced: " + value);
          buffer.add(value++);

          // Notify the consumer that an item is produced
          buffer.notify();

          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }

  static class Consumer implements Runnable {
    public void run() {
      while (true) {
        synchronized(buffer) {
          // Wait if the buffer is empty
          while (buffer.isEmpty()) {
            try {
              buffer.wait();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }

          int value = buffer.poll();
          System.out.println("Consumer consumed: " + value);

          // Notify the producer that an item is consumed
          buffer.notify();

          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
}

Sample Output:

Producer produced: 0
Producer produced: 1
Consumer consumed: 0
Consumer consumed: 1
Producer produced: 2
Producer produced: 3
Producer produced: 4
Producer produced: 5
Producer produced: 6
Consumer consumed: 2
Consumer consumed: 3
Consumer consumed: 4
Consumer consumed: 5
Consumer consumed: 6
Producer produced: 7
Producer produced: 8
Producer produced: 9
Producer produced: 10
Producer produced: 11
................................... 
...................................

Explanation:

In the above exercise -

  • The "Producer" class implements the Runnable interface and represents the producer thread. It continuously produces items by adding values to the shared buffer. When the buffer is full, the producer waits until the consumer consumes an item and notifies it.
  • The "Consumer" class also implements the Runnable interface and represents the consumer thread. It continuously consumes items by removing values from the shared buffer. As soon as the buffer is empty, the consumer uses the wait() method to wait until a new item is produced by the producer.
  • In the main() method, we create instances of the Producer and Consumer classes as separate threads and start them concurrently.

Flowchart:

Flowchart: Java Program with wait() and notify() for Thread Synchronization.
Flowchart: Java Program with wait() and notify() for Thread Synchronization.
Flowchart: Java Program with wait() and notify() for Thread Synchronization.

Sample Solution-2:

The code we provided above has a potential issue with deadlock, and using notifyAll() is a good solution to avoid it. Here's an updated version of the above code with notifyAll():

Java Code:

// ProducerConsumer.java
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumer {
  private static final int BUFFER_SIZE = 5;
  private static final Queue<Integer> buffer = new LinkedList<>();
  public static void main(String[] args) {
    // Create producer and consumer threads
    Thread producerThread = new Thread(new Producer());
    Thread consumerThread = new Thread(new Consumer());
    // Start producer and consumer threads
    producerThread.start();
    consumerThread.start();
  }
  // Producer thread class
  static class Producer implements Runnable {
    public void run() {
      int value = 0;
      while (true) {
        synchronized (buffer) {
          // Wait if the buffer is full
          while (buffer.size() == BUFFER_SIZE) {
            try {
              buffer.wait();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          // Produce item and add to the buffer
          System.out.println("Producer produced: " + value);
          buffer.add(value++);
          // Notify all consumers that an item is produced
          buffer.notifyAll();
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
  // Consumer thread class
  static class Consumer implements Runnable {
    public void run() {
      while (true) {
        synchronized (buffer) {
          // Wait if the buffer is empty
          while (buffer.isEmpty()) {
            try {
              buffer.wait();
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          // Consume item from the buffer
          int value = buffer.poll();
          System.out.println("Consumer consumed: " + value);
          // Notify all producers that an item is consumed
          buffer.notifyAll();
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
}

Sample Output:

Producer produced: 0
Producer produced: 1
Producer produced: 2
Producer produced: 3
Producer produced: 4
Consumer consumed: 0
Consumer consumed: 1
Consumer consumed: 2
Consumer consumed: 3
Consumer consumed: 4
Producer produced: 5
Producer produced: 6
Producer produced: 7
Producer produced: 8
Producer produced: 9
Consumer consumed: 5
Consumer consumed: 6
Consumer consumed: 7
.........
.........

Java Code Editor:

Improve this sample solution and post your code through Disqus

Previous: Java Program to Create and Start Multiple Threads.
Next: Synchronizing Threads with ReentrantLock for Shared Resource.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.