Inter-thread communication

Inter-thread communication in Java involves the coordination of threads to ensure they work together correctly without conflicts. This is essential in multithreaded applications to avoid issues such as race conditions, deadlocks, and inconsistent data states. Java provides several mechanisms and constructs for inter-thread communication

Understanding Inter-Thread Communication

When multiple threads share a resource, sometimes one thread must pause its execution until another thread completes its work. For example, in a producer-consumer scenario, a consumer thread might have to wait until the producer provides data. Rather than continuously checking (polling) the resource, Java allows a thread to suspend itself and wait until it receives a notification from another thread.

This is where wait(), notify(), and notifyAll() come into play:

  • wait() causes the current thread to wait until another thread invokes notify() or notifyAll() on the same object.

  • notify() wakes up a single waiting thread.

  • notifyAll() wakes up all threads waiting on the object’s monitor.

Method Descriptions

1. wait()

public final void wait() throws InterruptedException

Causes the current thread to wait until another thread notifies it.
The thread releases the lock and goes into a waiting state.Code language: PHP (php)

  2. notify()

public final void notify()

Wakes up one thread waiting on the object's monitor.
The awakened thread must reacquire the lock before resuming execution.Code language: PHP (php)

 3. notifyAll()

public final void notifyAll()

Wakes up all threads waiting on the object's monitor.
Threads compete for the lock; only one thread acquires it and continues.Code language: PHP (php)

  Program Implementation

The Producer-Consumer problem is a classic example of a multi-threading synchronization issue, where two or more threads share a common resource. One or more producer threads generate data  while one or more consumer threads take data  for processing.

//ProducerConsumerDemo.java
class SharedResource {
    private int data;
    private boolean isDataAvailable = false;

    // Synchronized produce method for the producer thread
    public synchronized void produce(int value) {
        // If data is available, producer has to wait until consumer consumes it
        while (isDataAvailable) {
            try {
                wait(); // Wait until the data is consumed
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // Handle thread interruption
            }
        }
        // Produce data
        data = value;
        isDataAvailable = true; // Data is now available
        System.out.println("Produced: " + value);
        notifyAll(); // Notify all waiting threads (consumer) that new data is available
    }

    // Synchronized consume method for the consumer thread
    public synchronized int consume() {
        // If no data is available, consumer has to wait until producer produces it
        while (!isDataAvailable) {
            try {
                wait(); // Wait until data is produced
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // Handle thread interruption
            }
        }
        // Consume data
        isDataAvailable = false; // Data is now consumed
        System.out.println("Consumed: " + data);
        notifyAll(); // Notify all waiting threads (producer) that the data has been consumed
        return data;
    }
}

public class ProducerConsumerDemo {
    public static void main(String[] args) {
        SharedResource resource = new SharedResource();

        // Producer thread
        Thread producer = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                resource.produce(i); // Produce data
            }
        });

        // Consumer thread
        Thread consumer = new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                resource.consume(); // Consume data
            }
        });

        // Start both producer and consumer threads
        producer.start();
        consumer.start();
    }
}

/*
C:\>javac ProducerConsumerDemo.java

C:\>java ProducerConsumerDemo
Produced: 1
Consumed: 1
Produced: 2
Consumed: 2
Produced: 3
Consumed: 3
Produced: 4
Consumed: 4
Produced: 5
Consumed: 5
Produced: 6
Consumed: 6
Produced: 7
Consumed: 7
Produced: 8
Consumed: 8
Produced: 9
Consumed: 9
Produced: 10
Consumed: 10
*/

Inter-thread communication using wait(), notify(), and notifyAll() methods is a powerful and efficient mechanism for coordinating threads in Java. It enables threads to work together smoothly without the need for constant checking or inefficient spinning. Proper understanding and careful use of these methods lead to efficient, synchronized, and deadlock-free multi-threaded programs. Mastery of this concept is essential for writing robust concurrent Java applications.

Scroll to Top