====== Usage of wait and notify in Producer - Consumer problem ====== In Java, **wait**, **notify**, and **notifyAll** are methods used for inter-thread communication. They are part of the Object class and are used to coordinate activities between threads. In this example, we'll create a simple **producer-consumer** scenario where the producer produces data into a shared resource (a queue, in this case), and the consumer consumes it. We'll use **wait** and **notify** to handle the communication between producer and consumer. 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(); } } **Producer Method**: Produces an item and adds it to the queue. If the queue is full, the producer thread waits (wait()). Once an item is produced, it notifies (notify()) the consumer thread. **Consumer Method**: Consumes an item from the queue. If the queue is empty, the consumer thread waits. After consuming an item, it notifies the producer thread. **Wait and Notify**: These methods are used to efficiently use resources. The producer waits if the queue is full, and the consumer waits if it is empty. Once an item is produced or consumed, producer and consumer notify each other. ** Synchronized Block**: Both wait and notify are called within a synchronized block to ensure that the thread holds the monitor's lock. This example showcases a typical use case for wait and notify in Java, facilitating smooth and efficient communication between threads, especially in scenarios involving resource sharing.