🧵 Producer-Consumer Problem in Java (Classic Wait/Notify)

VijayVijay
2 min read

The Producer-Consumer problem is a classic example of a multi-threading problem where:

  • The Producer creates data and puts it in a shared buffer.

  • The Consumer takes data from that buffer.

  • Synchronization ensures they don’t interfere with each other and avoid issues like race conditions or data inconsistency.

✅ Requirements:

  • Shared bounded buffer

  • Producer waits if the buffer is full

  • Consumer waits if the buffer is empty

  • Use wait() and notifyAll() for coordination

Java Code

import java.util.LinkedList;
import java.util.Queue;

public class ProducerConsumerLambda {
    public static void main(String[] args) {
        final Queue<Integer> buffer = new LinkedList<>();
        final int capacity = 5;

        Thread producer = new Thread(() -> {
            int value = 0;
            while (true) {
                synchronized (buffer) {
                    while (buffer.size() == capacity) {
                        try {
                            buffer.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    buffer.add(value);
                    System.out.println("Produced: " + value++);
                    buffer.notifyAll();
                }

                try {
                    Thread.sleep(500); // Simulate production time
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        Thread consumer = new Thread(() -> {
            while (true) {
                synchronized (buffer) {
                    while (buffer.isEmpty()) {
                        try {
                            buffer.wait();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                    int value = buffer.remove();
                    System.out.println("Consumed: " + value);
                    buffer.notifyAll();
                }

                try {
                    Thread.sleep(1000); // Simulate consumption time
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });

        producer.start();
        consumer.start();
    }
}

📌 Key Points:

  • synchronized ensures mutual exclusion on buffer methods.

  • wait() makes the thread release the lock and wait until notified.

  • notifyAll() wakes up all waiting threads so they can recheck conditions.

  • This solution prevents buffer overflows and underflows.

0
Subscribe to my newsletter

Read articles from Vijay directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Vijay
Vijay