If you ask me one concept in Java which is so obvious yet most misunderstood, I would say the wait(), notify() and notifyAll() methods. They are quite obvious because they are the one of the three methods of total 9 methods from java.lang.Object but if you ask when to use the wait(), notify() and notfiyAll() in Java, not many Java developer can answer with surety. The number will go down dramatically if you ask them to solve the producer-consumer problem using wait() and notify(). Many will use if block instead of while loop, many others will get confused on which object they should call wait() and notify()method? Some of them even succeed in creating livelock, deadlock, and other multithreading issues.
That's why it's become very important to know as much as possible about these three methods. In this article, I am going to share some practical tips and points about wait(), notify() and notifyAll() in Java.
Two books, which helped me a lot while understanding this core concept are Effective Java and Core Java Volume 1 - Fundamentals by Cay S. Horstmann. Both of them explains this confusing concept in simple language. The two items on Effective Java is the two of the best piece to read on this topic.
when to use wait() and notify() method in Java
wait() vs notify() vs notifyAll in threading
Let's see some key points about these fundamental methods in Java especially from multi-threading and concurrency perspective.
1) Though wait, notify and notifyAll are related to threads they are not defined in java.lang.Thread class, instead they are defined in the Object class. If you are wondering why? then you should read why the wait() and notify() are defined in Object class in Java.
2) You must call the wait(), notify() and notifyAll() methods from a synchronized context in Java i.e. inside synchronized method or a synchronized block. The thread must hold the lock on the object it is going to call the wait() or notify() method and that is acquired when it enter into a synchronized context.
If you call it without holding a lock then they will throw IllegalMonitorStateException in Java. If you are curious why is this restriction in place then check this article to learn more.
3) You must call wait() method from inside a loop, don't call with an if block because a thread can sporadically awake from the wait state without being notified by another party. If you use if block then this could result in a bug. You can also see Item 69 of Effective Java for more details.
Here is the standard idiom to call the wait() method in Java:
synchronized (theSharedObject) {
while (condition) {
theSharedObject.wait();
}
// do something
}
4) When a thread calls the wait() method in Java, it goes to the wait state by releasing the lock, which is later acquired by the other thread who can notify this thread. Here is a nice diagram of how state transition of a thread happens in Java:
wait and notify in Java
5) A thread waiting due to a call to wait() method can wake up either by notification e.g. calling notify() or notifyAll() method on the same object or due to interruption.
6) The wait() method throws InterrruptedException in Java, which is a checked exception. You must provide a handler for this, but it's your choice whether you really want to handle the interruption or not.
7) You must call wait() method on shared object e.g. in producer-consumer problem, the task queue is shared between producer and the consumer thread. In order to communicate, you must use that queue on synchronized block and subsequently called wait() method on queue e.g. queue.wait().
The other thread should also call the notify() or notifyAll() method on same shared object i.e. queue.notify() or queue.notifyAll(). You can also see my post how to do inter-thread communication in Java for more details.
inter thread communication in Java using wait notify
8) When you call the notify() method on a shared object and if more than one thread is waiting on that lock then anyone of them will get the notification, which thread will get the notification is not guaranteed. If only one thread is waiting then it will get the notification.
9) When you call the notifyAll() method on shared object and if more than one thread is waiting for notification then all of them will receive the notification but who will get the CPU to start execution is not guaranteed. It depends on upon thread scheduler. Which means it's possible for a thread to get the notification, but it might go to the wait state again if the condition for wait still holds true, mainly due to other thread's processing.
For example, suppose 5 people are waiting for food and they all hear the notification that food has arrived, but only of them goes past the door and eat food. When next people's chance come to go past the door food is already finished so it goes to the wait state again. See Core Java Volume 1 - Fundamentals by Cay S. Horstmann to learn more about notify() and notifyAll() in Java.
difference between wait, notify and notifyAll in Java
10) Main difference between notify() and notifyAll() is that in case of notify() only one of the waiting thread gets a notification but in case of notifyAll() all thread get notification. You can also read the real difference between notify() and notifyAll() to learn more
That's all about wait(), notify() and notifyAll() methods in Java. These are three of the most important methods every Java developer should know. It's key to implement inter-thread communication in Java. You should try writing code using wait() and notify() method by hand or by using notepad to learn the concept better.