• Home
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All
  • About
Java | Object Class Methods: wait, notify, notifyAll
  1. The methods wait, notify
  2. The method notifyAll

  1. The methods wait, notify
    If the execution of code depends on the state of an object in order to read or modify its attributes or invoke its methods, then it is possible to put the thread executing this code on hold, waiting for another thread that manipulates the object to send a notification indicating that the object is now ready to be used.

    For example, if an application uses two threads, where:
    • one is responsible for constructing the elements of an array,
    • and the other is responsible for sorting the array elements once all elements have been provided.
    Then, both threads can use the wait and notify methods to synchronize access to this object.
    package com.mtitek.threads;
    
    class MyClass {
        private volatile boolean ready = false;
        private Integer[] elements;
    
        public synchronized boolean isReady() {
            return ready;
        }
    
        public synchronized void setReady(boolean ready) {
            this.ready = ready;
        }
    
        public synchronized Integer[] getElements() {
            return elements;
        }
    
        public synchronized void setElements(Integer[] elements) {
            this.elements = elements;
        }
    }
    
    public class MainClass {
        public static void main(String[] args) {
            final MyClass myClass = new MyClass();
    
            Runnable myRunnable1 = new Runnable() {
                @Override
                public void run() {
                    synchronized (myClass) {
                        try {
                            // Wait while another thread might be using the object
                            while (myClass.isReady()) {
                                myClass.wait();
                            }
    
                            // Code to be executed by the thread
                            System.out.println(
                                    Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ")");
    
                            System.out.println("Initializing array elements (start)");
    
                            myClass.setElements(new Integer[] { 4, 2, 8, 1, 6 });
    
                            System.out.println("Initializing array elements (end)");
    
                            // Mark as ready and notify waiting threads
                            myClass.setReady(true);
                            myClass.notify();
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt(); // Restore interrupted status
                            System.err.println(Thread.currentThread().getName() + " was interrupted: " + e.getMessage());
                        }
                    }
                }
            };
    
            Runnable myRunnable2 = new Runnable() {
                @Override
                public void run() {
                    synchronized (myClass) {
                        try {
                            // Wait until data is ready
                            while (!myClass.isReady()) {
                                myClass.wait();
                            }
    
                            // Process the data
                            System.out.println(
                                    Thread.currentThread().getName() + " (" + Thread.currentThread().threadId() + ")");
    
                            System.out.println("Sorting and displaying array elements (start)");
    
                            Integer[] elements = myClass.getElements();
                            if (elements != null) {
                                // Sort the array
                                java.util.Arrays.sort(elements);
    
                                for (Integer element : elements) {
                                    System.out.println(element);
                                }
                            }
    
                            System.out.println("Sorting and displaying array elements (end)");
    
                            // Reset state and notify
                            myClass.setReady(false);
                            myClass.notify();
    
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt(); // Restore interrupted status
                            System.err.println(Thread.currentThread().getName() + " was interrupted: " + e.getMessage());
                        }
                    }
                }
            };
    
            Thread myThread1 = new Thread(myRunnable1, "myFirstThread");
            Thread myThread2 = new Thread(myRunnable2, "mySecondThread");
    
            myThread1.start();
            myThread2.start();
    
            // Wait for threads to complete
            try {
                myThread1.join();
                myThread2.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("Main thread was interrupted: " + e.getMessage());
            }
        }
    }
    Output:
    myFirstThread (19)
    Initializing array elements (start)
    Initializing array elements (end)
    mySecondThread (20)
    Sorting and displaying array elements (start)
    1
    2
    4
    6
    8
    Sorting and displaying array elements (end)
  2. The method notifyAll
    The notifyAll method is used to wake up all threads that are currently waiting on the same object's monitor. Unlike notify, which wakes only one waiting thread (chosen arbitrarily by the JVM), notifyAll ensures that all waiting threads become eligible for scheduling and will compete for the monitor lock.

    This is particularly useful when multiple threads might be waiting for different conditions related to the same object, or when you want to ensure all waiting threads get a chance to re-evaluate their waiting conditions.
    package com.mtitek.threads;
    
    public class MainClass {
        public static void main(String[] args) {
            final Object lock = new Object();
    
            Runnable myRunnable = new Runnable() {
                @Override
                public void run() {
                    synchronized (lock) {
                        try {
                            System.out.println(Thread.currentThread().getName() + " is waiting.");
                            lock.wait();
                            System.out.println(Thread.currentThread().getName() + " has been notified and resumed.");
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt(); // Restore interrupted status
                            System.err.println(Thread.currentThread().getName() + " was interrupted: " + e.getMessage());
                        }
                    }
                }
            };
    
            // Create and start two threads that will wait on the same lock
            Thread myThread1 = new Thread(myRunnable, "myFirstThread");
            Thread myThread2 = new Thread(myRunnable, "mySecondThread");
    
            myThread1.start();
            myThread2.start();
    
            // Pause to ensure all threads are waiting
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("Main thread was interrupted: " + e.getMessage());
                return;
            }
    
            // Notifier thread
            Thread notifierThread = new Thread(() -> {
                synchronized (lock) {
                    System.out.println("NotifierThread is calling notifyAll.");
                    lock.notifyAll(); // Wake up all waiting threads
                }
            }, "NotifierThread");
    
            notifierThread.start();
    
            // Wait for all threads to complete
            try {
                myThread1.join();
                myThread2.join();
                notifierThread.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.err.println("Main thread was interrupted: " + e.getMessage());
            }
        }
    }
    Output:
    myFirstThread is waiting.
    mySecondThread is waiting.
    NotifierThread is calling notifyAll.
    myFirstThread has been notified and resumed.
    mySecondThread has been notified and resumed.
© 2025  mtitek