Java.Core.WaitAndNotifyExample

code

class SharedResource {
    synchronized void waitForSignal() throws InterruptedException {
        System.out.println("Waiting...");
        wait(); // Thread will wait until notified
        System.out.println("Got signal!");
    }

    synchronized void sendSignal() {
        notify(); // Notifies one waiting thread
        System.out.println("Signal sent!");
    }
}

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

        // Thread 1: Calls waitForSignal() and waits
        new Thread(() -> {
            try {
                resource.waitForSignal();
            } catch (InterruptedException e) { }
        }).start();

        // Thread 2: Calls sendSignal() after 1 second
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                resource.sendSignal();
            } catch (InterruptedException e) { }
        }).start();
    }
}

Step-by-Step Execution

  1. Thread 1 (waitForSignal()) starts first
    • Prints “Waiting…”.
    • Calls wait(), which releases the lock on resource and goes into waiting state.
  2. Thread 2 (sendSignal()) starts after 1 second
    • Calls sendSignal(), acquires the lock, and calls notify(), which wakes up Thread 1.
    • Prints “Signal sent!”.
    • Releases the lock.
  3. Thread 1 resumes execution
    • Continues after wait().
    • Prints “Got signal!”.

Expected Output

Waiting...
Signal sent!
Got signal!

Explanation of Output

EventThreadOutput Printed
Thread 1 starts and calls wait()Thread 1Waiting...
Thread 2 starts after 1 second, calls notify()Thread 2Signal sent!
Thread 1 resumes after being notifiedThread 1Got signal!

Order of execution is guaranteed because:

  • Thread 1 must print “Waiting…” before it goes into waiting.
  • Thread 2 must print “Signal sent!” after it wakes up Thread 1.
  • Thread 1 then resumes and prints “Got signal!”.

What Happens If We Don’t Use Thread.sleep(1000)?

If we remove the delay from Thread 2, the execution order may change depending on thread scheduling, but the logical order remains the same.

Would you like to modify this example to use notifyAll() instead of notify()? 🚀

What Happens When Multiple Threads Are Waiting on notify()?

When you have multiple threads waiting on an object’s wait() method and only one thread calls notify(), only one of the waiting threads is randomly chosen to wake up.


Example: Three Threads Waiting on notify()

class SharedResource {
    synchronized void waitForSignal() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " is Waiting...");
        wait(); // Thread goes into waiting state
        System.out.println(Thread.currentThread().getName() + " Got signal!");
    }

    synchronized void sendSignal() {
        notify(); // Notifies only ONE waiting thread
        System.out.println("Signal sent by " + Thread.currentThread().getName());
    }
}

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

        // Three threads waiting for a signal
        Thread t1 = new Thread(() -> {
            try { resource.waitForSignal(); } catch (InterruptedException e) {}
        }, "Thread-1");

        Thread t2 = new Thread(() -> {
            try { resource.waitForSignal(); } catch (InterruptedException e) {}
        }, "Thread-2");

        Thread t3 = new Thread(() -> {
            try { resource.waitForSignal(); } catch (InterruptedException e) {}
        }, "Thread-3");

        // Start all waiting threads
        t1.start();
        t2.start();
        t3.start();

        // Sleep to ensure all threads are waiting before sending a signal
        try { Thread.sleep(1000); } catch (InterruptedException e) {}

        // One thread will be notified
        new Thread(() -> resource.sendSignal(), "Notifier").start();
    }
}

Expected Output (Order May Vary)

Thread-1 is Waiting...
Thread-2 is Waiting...
Thread-3 is Waiting...
Signal sent by Notifier
Thread-2 Got signal!

🛑 Only one thread (e.g., Thread-2) is notified, while the others remain waiting.


Which Thread Receives the Signal?

  • notify() wakes up only ONE thread randomly from the waiting queue.
  • The choice of which thread wakes up is NOT predictable (depends on JVM scheduling).

If You Want to Wake Up All Waiting Threads

  • Use notifyAll() instead of notify().
  • This wakes up all waiting threads, but they still need to compete for the lock.

Example Using notifyAll()

synchronized void sendSignal() {
    notifyAll(); // Wakes up ALL waiting threads
    System.out.println("All threads notified by " + Thread.currentThread().getName());
}

Expected Output of notifyAll()

Thread-1 is Waiting...
Thread-2 is Waiting...
Thread-3 is Waiting...
All threads notified by Notifier
Thread-1 Got signal!
Thread-2 Got signal!
Thread-3 Got signal!

📌 Note: Even though all threads wake up, only one thread can proceed at a time because of the synchronized block.


Summary

MethodEffect
notify()Wakes up only one waiting thread (chosen randomly).
notifyAll()Wakes up all waiting threads, but they still compete for the lock.
This entry was posted in Без рубрики. Bookmark the permalink.

Leave a Reply

Your email address will not be published.