Effective Java Thread Communication: A Comprehensive Guide

Java Thread Communication

Java thread communication is a fundamental concept that enables multiple threads to operate effectively, especially when sharing resources. This guide outlines the essential points of thread communication in Java, making it accessible for beginners.

Key Concepts

1. Threads in Java

  • A thread is a lightweight process that can run concurrently with other threads.
  • Threads in Java can be created by extending the Thread class or implementing the Runnable interface.

2. Thread Communication

  • Since multiple threads may access shared resources, communication between threads is crucial to avoid conflicts and ensure data integrity.
  • Java provides several methods to facilitate communication between threads.

Important Methods

1. wait()

  • The wait() method is called on an object and causes the current thread to pause execution until another thread invokes notify() or notifyAll() on the same object.
  • This method releases the lock on the object and allows other threads to acquire it.

2. notify()

  • The notify() method wakes up a single thread that is waiting on the object's monitor.
  • This is used to signal that a thread can resume execution.

3. notifyAll()

  • The notifyAll() method wakes up all threads that are waiting on the object's monitor.
  • This is useful when multiple threads are waiting for a resource to become available.

Example of Thread Communication

Here’s a simple example demonstrating thread communication using wait(), notify(), and notifyAll():

class SharedResource {
    private int data;
    private boolean available = false;

    public synchronized int getData() throws InterruptedException {
        while (!available) {
            wait(); // Wait until data is available
        }
        available = false;
        notify(); // Notify producer
        return data;
    }

    public synchronized void setData(int data) {
        while (available) {
            try {
                wait(); // Wait until data is consumed
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.data = data;
        available = true;
        notify(); // Notify consumer
    }
}

class Producer extends Thread {
    private SharedResource resource;

    public Producer(SharedResource resource) {
        this.resource = resource;
    }

    public void run() {
        for (int i = 0; i < 5; i++) {
            resource.setData(i);
            System.out.println("Produced: " + i);
        }
    }
}

class Consumer extends Thread {
    private SharedResource resource;

    public Consumer(SharedResource resource) {
        this.resource = resource;
    }

    public void run() {
        for (int i = 0; i < 5; i++) {
            try {
                int data = resource.getData();
                System.out.println("Consumed: " + data);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Explanation of the Example

  • SharedResource Class: Contains methods for producing and consuming data; uses wait() and notify() for synchronization.
  • Producer Class: Produces integers and sets them in the shared resource.
  • Consumer Class: Consumes integers from the shared resource.

Conclusion

Understanding thread communication is essential for managing shared resources in a multi-threaded environment. By using methods like wait(), notify(), and notifyAll(), Java allows threads to communicate efficiently, preventing issues like resource contention and ensuring smooth execution.