Tuesday, August 27, 2013

Thread Communication with Wait(), Notify() & NotifyAll() in Java

In multi-threaded programs, often there is a need for one thread to communicate to another thread. The wait/notify mechanism is useful when threads must communicate in order to provide a functionality. The Object class has three methods, wait(), notify(), and notifyAll() that help threads communicate about the status of an event that the threads care about. In this post, we'll try to create a basic understanding of the most confusing concept of thread communication using methods wait(), notify() and notifyAll(). If you want to go through the Thread basic check this post


Classes that provide necessary support for concurrency in Java
  • Object : has methdods wait(), notify(), notifyAll() etc which are useful for multi-threading.
  • Thread Class
  • Runnable interface
As you every class extends Object class, so all object have some basic multi-threading capability.


In multi-threaded programs, often there is a need for one thread to communicate to another thread. The wait/notify mechanism is useful when threads must communicate in order to provide a functionality.
The method wait() allows the calling thread to wait for the wait object (on which wait() is called). In other words, if you want to make a thread wait for another thread, you can ask it to wait for the wait object using the wait() method. A thread remains in the wait state until some another thread calls the notify() or notifyAll() method on the wait object.


**One key point to remember (and keep in mind for the exam) about wait/notify is this:
wait() notify() and notifyAll() must be called from within a synchronized context! A thread can't invoke a wait or notify method on an object unless it owns that object's lock

Note that if the thread calling wait() does not own the lock, it will throw an IllegalMonitorStateException. This exception is not a checked exception,so you don't have to catch it explicitly. You should always be clear whether a thread has the lock of an object in any given block of code.


Let's first go through a basic example
I have on thread ThreadB other than main thread that calculate the sum of number meanwhile main() thread wait for ThreadB to notify when calculation is doneIt may look complex to you first time if you are using notify(), wait() methods first time. So keep patience!


Try to run the code and observe the output:


In the above example, main thread is waiting for threadB to complete. When ThreadB complete the processing it notify the main thread with notifyAll() method.

This how wait() and notify() communicate..!

May be some of you wondering above sceanrio can be implemented with the help of join() method?
Yes, that's true, see the below example



** The wait() and notify() methods are designed to provide a way to allow a thread to block until specific condition is met. For instance, In case of producer consumer problem, there will be a specific condition where producer or consumer wait i.e, when queue is empty consumer will wait and when queue is full producer will wait.
So,the first thing you have to do is to identify the conditions that you want the methods to wait for.

Following thing to remember while using wait and notify or notifyAll method in Java

  • use notifyAll instead of notify if you expect more than one thread is waiting for lock.
  • wait and notify method must be called in synchronized context
  • use same object for calling wait() and notify() method, every object has its own lock so calling wait() on object A and notify() on object B will not make any sense.

Wait() does not block the thread on which it is called; it blocks the current thread until notify() is called on the same object.
For instance, If you have threads A and B and, while in thread A, called B.wait(), this will stop thread A and not thread B - for as long as B.notify() is not called.

If you still having doubt till this line, please go again before going further because if you are clear about the above point then it will be easy to understand.

Now we'll take an example where two thread communicate where these two thread print the integer value from 1,2,3 ...so on turn by turn.
As I said earlier we need specific condition where these thread will wait for other, so in this example we take a Boolean variable as a specific condition where thread will wait. When it's value is true one thread will wait and when it's false other will wait.

Now see the below example that I created


Execute the above code and observe the output and try to add comments to see the flow as per your need to clear doubt.

Coffee Shop Simulation 
To further understand the wait/notify mechanism, you are going to simulate this coffee shop situation in a program. You can implement the coffee machine as one thread and the waiter as another thread in two different classes. The coffee machine can notify the waiter to take the coffee, and it can wait until the waiter has taken the coffee from the tray. Similarly, the waiter can take the coffee if it is available and notify the coffee machine to make another cup.


Producer Consumer problem
Producer Consumer is one of the classical concurrency problem. As there are many way to solve this problem, here I explained with help of wait(),notify() methods.
In the following code, ArrayList is take as source where producer can put the data and from where consumer consume the data. Here I'm adding one 5 values in ArrayList instead of adding infinite value for the demo purpose. If you understand the example, then you can modify and try yourself

Simulation on the basis of Name of player
As we have already seen the example above where thread printing the value turn wise. Now we implement the same in different way.
Now there will be two player, who will increment the value turn wise. Now the specific condition will be player name instead of boolean flag. Instead of creating ThreadFirst and ThreadSecond we'll create only one Thread and two instance of the same thread will be used.

This way you can implement the previous problem also.
I hope so you got the idea how we use notify(), notifyAll() and wait() methods to implement thread communication.
Best of luck!

When to use notify() and notifyAll()?
Let's examine the subtle difference between these two calls. The notify() method wakes up one thread waiting for the lock (the first thread that called wait() on that lock). The notifyAll() method wakes up all the threads waiting for the lock; the JVM selects one of the threads from the list of threads waiting for the lock and wakes that thread up.

In the case of a single thread waiting for a lock, there is no significant difference between notify() and notifyAll(). However, when there is more than one thread waiting for the lock, in both notify() and notifyAll(), the exact thread woken up is under the control of the JVM and you cannot programmatically control waking up a specific thread.


At first glance, it appears that it is a good idea to just call notify() to wake up one thread; it might seem unnecessary to wake up all the threads. However, the problem with notify() is that the thread woken up might not be the suitable one to be woken up (the thread might be waiting for some other condition, or the condition is still not satisfied for that thread etc). 
In that case, the notify() might be lost and no other thread will wake up potentially leading to a type of deadlock (the notification is lost and all other threads are waiting for notification—forever!).


To avoid this problem, it is always better to call notifyAll() when there is more than one thread waiting for a lock (or more than one condition on which waiting is done). the notifyAll() method wakes up all threads, so it is not very efficient. however, this performance loss is negligible in real world applications.

Related Post:
Daemon Thread in Java with Example
Detail info of Garbage Collection in Java
Basic concept of Thread in java
Interview 120+ Core java Question Answers


If you know anyone who has started learning Java, why not help them out! Just share this post with them. 
Thanks for studying today!...

4 comments: