import java.util.LinkedList; import java.util.Queue; public class WaitNotifyExample { private static final int CAPACITY = 5; private final Queue queue = new LinkedList<>(); public void produce() throws InterruptedException { int value = 0; while (true) { synchronized (this) { // Wait if the queue is full while (queue.size() == CAPACITY) { wait(); } // Producing an element and adding it to the queue System.out.println("Produced: " + value); queue.add(value++); // Notify the consumer that there is data available notify(); // Simulate time taken to produce an item Thread.sleep(1000); } } } public void consume() throws InterruptedException { while (true) { synchronized (this) { // Wait if the queue is empty while (queue.isEmpty()) { wait(); } // Consuming an element from the queue int value = queue.poll(); System.out.println("Consumed: " + value); // Notify the producer that there is space available notify(); // Simulate time taken to consume an item Thread.sleep(1000); } } } public static void main(String[] args) { WaitNotifyExample example = new WaitNotifyExample(); // Creating producer and consumer threads Thread producerThread = new Thread(() -> { try { example.produce(); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread consumerThread = new Thread(() -> { try { example.consume(); } catch (InterruptedException e) { e.printStackTrace(); } }); producerThread.start(); consumerThread.start(); } }