Tuesday, July 19, 2022

How to use wait, notify, and notifyAll in Java? Example Tutorial

When should you use the wait() and notify method in Java is one of the many popular questions about the wait and notify methods from Java multithreading interview questions. One of the reasons for its popularity is that still a lot of Java programmers struggle to explain and write code using wait-notify methods.  Many Java developer only knows some facts about the wait and notify methods like that wait() and notify() are defined in the java.lang.Object class or you cannot call wait() without synchronization, which means without a synchronized block or synchronized method but doesn't really know when and how to use them.

In this article, we will try to bridge that gap by going through a simple example of classical Producer-Consumer problems and show you how you can use them while writing concurrent Java applications for the real world.

First and foremost you should know that wait(), notify(), and notifyAll() are tools for inter-thread communication in Java. By using this method, you can tell a thread to stop working and later start processing.

They are the essential building block of Java multi-threading applications. In the real world, you can use the wait() and notify() method to implement a producer-consumer pattern where most of the multi-threaded application falls. 

If you don't know much about them, I suggest you join a fundamental course on Java threads like Multithreading and Parallel Computing in Java course from Udemy. It's also very affordable and you can get in just $9.9 on Udemy sales. 




How to use the wait() and notify() methods in Java?

You can use the wait() and notify() method to communicate between multiple threads, for example, you can tell one thread to stop working from another thread based upon some condition, later you can notify it to start processing again.

One of the popular examples of the wait() and notify() method is to solve the producer-consumer problem, where you can have either a single producer and a single consumer or multiple producers and a single consumer or just one producer and multiple consumers.

In this example, you will learn how to implement multiple producers and single consumer solutions using wait() and notify() in Java. If you are not familiar with notify and notifyAll method, you can further see The Complete Java Masterclass to learn more.

wait, notify, and nofityAll() Example in Java [Inter Thread Communication]




Wait-Notify Example  in Java for Producer-Consumer Problem 

package tool;
 
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
 
/**
 * A simple Java Program to demonstrate how to use wait
 * and notify() method ofr inter-thread communciation
 * in Java. 
 */
 
public class Hello {
 
  public static void main(String[] args) {
    Queue<String> q = new LinkedList<>();
    boolean exit = false;
    Producer p = new Producer(q, exit);
    p.start();
    Consumer c = new Consumer(q, exit);
    c.start();
 
  }
 
}
 
class Producer extends Thread {
  private volatile Queue<String> sharedQueue;
  private volatile boolean bExit;
 
  public Producer(Queue<String> myQueue, boolean bExit) {
    this.sharedQueue = myQueue;
    this.bExit = bExit;
  }
 
  public void run() {
    while (!bExit) {
      synchronized (sharedQueue) {
        while (sharedQueue.isEmpty()) {
          String item = String.valueOf(System.nanoTime());
          sharedQueue.add(item);
          System.out.println("Producer added : " + item);
          try {
            System.out.println("Producer sleeping by calling wait: " + item);
            sharedQueue.wait();
            System.out.println("Producer wake up: ");
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
}
 
class Consumer extends Thread {
  private volatile Queue<String> sharedQueue;
  private volatile boolean bExit;
 
  public Consumer(Queue<String> myQueue, boolean bExit) {
    this.sharedQueue = myQueue;
    this.bExit = bExit;
  }
 
  public void run() {
 
    while (!bExit) {
 
      synchronized (sharedQueue) {
        while (!sharedQueue.isEmpty()) {
          String item = sharedQueue.poll();
          System.out.println("Consumer removed : " + item);
          System.out.println("Consumer notifying Producer: " + item);
          sharedQueue.notify();
        }
      }
    }
  }
}
 
Output:
Producer added : 12275948008616
Producer sleeping by calling wait: 12275948008616
Consumer removed : 12275948008616
Consumer notifying Producer: 12275948008616
Producer wake up: 
Producer added : 12275948047960
Producer sleeping by calling wait: 12275948047960
Consumer removed : 12275948047960
Consumer notifying Producer: 12275948047960
Producer wake up: 
Producer added : 12275948082600
Producer sleeping by calling wait: 12275948082600
Consumer removed : 12275948082600
Consumer notifying Producer: 12275948082600




What's Happening Here? Explanation

Producer thread is producing items, adding them into a queue, and then going into wait() state until consumer thread consumes it. When the Consumer thread removes the items from the queue, it also notifies the Producer thread to start producing again. 

That's why you see an ordered output like Producer added, Producer Sleeping, Consumer Removed, Consumer Notified, and Producer Wakeup. In short, both Producer and Consumer Thread are talking with each other using the wait and notify method. 

If you remove that wait call then the Producer thread will keep checking for the queue to become waiting and keep wasting the CPU cycle. 

Similarly, if you remove the notify call then the waiting Producer thread may never wake up.  Btw, if you have trouble understanding Producer-Consumer Problem then I also suggest taking a look at  the 
Applying Concurrency and Multi-threading to Common Java Patterns course on Pluralsight.

When and How to use the wait() and notify(), nofityAll() metohd in Java?



Things to remember

1) Always call wait() from the synchronized context in Java, see here to learn why

2) Always check the waiting condition in a loop instead of if block in Java, see here to learn why.

3) Remember, you can wake up a waiting thread by using the interrupt() method but only if your waiting thread handles the interrupted exception.

4) Prefer notifyAll() over notify() if you are in doubt, see here to learn more.

5) Don't forget to call the wait() and notify() method on the same shared object.


That's all about when to use the wait and notify method in Java. It's a perfect and most native tool for inter-thread communication in Java. A good understanding of wait, notify, and the notifyAll method goes a long way in writing a robust and safe concurrent Java program. If you have any trouble understanding this problem, please drop a note and I'll try to explain.


Other Java Multithreading and Concurrency Articles you may like
  • 5 Best Online Courses to Learn Java Multithreading in-depth (courses)
  • Difference between volatile, synchronized, and atomic variable in Java (answer)
  • 10 Java Multithreading and Concurrency Best Practices (article)
  • Top 50 Multithreading and Concurrency Questions in Java (questions)
  • How to avoid deadlock in Java? (answer)
  • Top 5 Books to Master Concurrency in Java (books)
  • Difference between CyclicBarrier and CountDownLatch in Java? (answer)
  • How to pause a Thread in Java? (solution)
  • Difference between ForkJoinPool and Executor Framework in Java(answer)
  • 5 Essential Skills to Crack Java Interviews (skills)
  • Java CountDownLatch Examples for Beginners (example)
  • How to join two threads in Java? (answer)
  • Difference between Executor and ExecutorService in Java? (answer)
  • How to stop a Thread in Java? (answer)
  • What is Happens Before in Java Concurrency? (answer)

Thanks a lot for reading this article so far. If you like this example of wait, notify, and notifyall in Java for solving the producer-consumer problem then please share it with your friends and colleagues. If you have any questions or feedback then please drop a note.

P. S. - If you are a beginner in Java but keen to learn Java Multithreading and Concurrency and looking for a free online training course to start with then I also, suggest you check out this awesome free Java Multithreading course on Udemy. This course is absolutely free and thousands of java developers have already joined this course. 


1 comment:

  1. Very well explained, thank you. I always have doubt between whether to use loop or if condition and this example cleared that. How about using BlokcingQueue or any other higher order classes for implementing producer consumer patter

    ReplyDelete

Feel free to comment, ask questions if you have any doubt.