Tuesday, 28 January 2014

Difference between notify and notifyAll in Java - When and How to use

notify vs notifyAll in Java
What is difference between notify and notifyAll method is one of the tricky Java question, which is easy to answer but once Interviewer ask followup questions, you either got confused or not able to provide clear cut and to the point answers. Main difference between notify and notifyAll is that notify method will only notify one Thread and notifyAll method will notify all Threads  which are waiting on that monitor or lock. By the way this is something you have been reading in all over places and to be frank,  this statement despite being correct is not complete and its very difficult to understand difference between notify vs notifyAll by just reading this statement. Lot of questions comes in mind like

Which thread will be notified if I use notify()?
How do I know how many threads are waiting, so that I can use notifyAll() ?
How to call notify()?
What are these thread waiting for being notified etc.

Actually discussion of notify and notifyAll is incomplete without discussing wait method in Java and I had touched based on this on my earlier article why wait and notify must be called from synchronized context. In order to get answer of those questions and understand difference between notify and notifyAll we will use a simple Java Thread example using wait and notify code :


Difference between notify and notifyAll in Java
Difference between notify and notifyAll in Java with ExampleJava provides two methods notify and notifyAll for waking up threads waiting on some condition and you can use any of them but there is subtle difference between notify and notifyAll in Java which makes it one of the popular multi-threading interview question in Java. When you call notify only one of waiting thread will be woken and its not guaranteed which thread will be woken, it depends upon Thread scheduler. While if you call notifyAll method, all threads waiting on that lock will be woken up, but again all woken thread will fight for lock before executing remaining code and that's why wait is called on loop because if multiple threads are woken up, the thread which will get lock will first execute and it may reset waiting condition, which will force subsequent threads to wait. So key difference between notify and notifyAll is that notify() will cause only one thread to wake up while notifyAll method will make all thread to wake up.


When to use notify and notifyAll in Java
This is the follow-up question if you get pass the earlier one Difference between notifyAll and notify in Java. If you understand notify vs notifyAll then you can answer this by applying little common sense. You can use notify over notifyAll if all thread are waiting for same condition and only one Thread at a time can benefit from condition becoming true. In this case notify is optimized call over notifyAll because waking up all of them because we know that only one thread will benefit and all other will wait again, so calling notifyAll method is just waste of cpu cycles. Though this looks quite reasonable there is still a caveat that unintended recipient swallowing critical notification. by using notifyAll we ensure that all recipient will get notify. Josh bloach has explained this in good detail in his book Effective Java , I highly recommend this book if you haven't read them already. Another one you can try is Concurrency Practice in Java and Java Thread, which discusses wait and notify methods in good details.

Example of notify and notifyAll method in Java

I have put together an example to show how all threads gets notified when we call notifyAll method in Java and just one Thread will wake up when we call notify method in Java. In this example three threads will wait if boolean variable go is false, remember boolean go is a volatile variable, so that all threads will see its updated value. Initially three threads WT1, WT2, WT3 will wait because variable go is false than one thread NT1 will make go true and notify all threads by calling notifyAll method or notify just one thread by calling notify() method. In case of notify() call there is no guarantee which thread will woke up and you can see it by running this Java program multiple times. In case of notifyAll all thread will woke up but they will compete for monitor or lock and the Thread which will get the lock first will finish its execution and resetting go to false which will force other two threads still waiting. At the end of this program you will have two threads waiting and two threads including notification thread finished. Program will not terminate because other two threads are still waiting and they are not daemon threads. Purpose of this notify and notifyAll example is to show you How to use them and How notify and notifyAll method works in Java.

Code Example of notify and notifyAll
Here is complete code example of How to use notify and notifyAll method in Java. We have already explained when to use notify vs notifyAll method and this example will clarify effect of calling notify and notifyAll method  in Java.

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Java program to demonstrate How to use notify and notifyAll method in Java and
 * How notify and notifyAll method notifies thread, which thread gets woke up etc.
 */

public class NotificationTest {

    private volatile boolean go = false;

    public static void main(String args[]) throws InterruptedException {
        final NotificationTest test = new NotificationTest();
     
        Runnable waitTask = new Runnable(){
     
            @Override
            public void run(){
                try {
                    test.shouldGo();
                } catch (InterruptedException ex) {
                    Logger.getLogger(NotificationTest.class.getName()).
                           log(Level.SEVERE, null, ex);
                }
                System.out.println(Thread.currentThread() + " finished Execution");
            }
        };
     
        Runnable notifyTask = new Runnable(){
     
            @Override
            public void run(){
                test.go();
                System.out.println(Thread.currentThread() + " finished Execution");
            }
        };
     
        Thread t1 = new Thread(waitTask, "WT1"); //will wait
        Thread t2 = new Thread(waitTask, "WT2"); //will wait
        Thread t3 = new Thread(waitTask, "WT3"); //will wait
        Thread t4 = new Thread(notifyTask,"NT1"); //will notify
     
        //starting all waiting thread
        t1.start();
        t2.start();
        t3.start();
     
        //pause to ensure all waiting thread started successfully
        Thread.sleep(200);
     
        //starting notifying thread
        t4.start();
     
    }
    /*
     * wait and notify can only be called from synchronized method or bock
     */

    private synchronized void shouldGo() throws InterruptedException {
        while(go != true){
            System.out.println(Thread.currentThread()
                         + " is going to wait on this object");
            wait(); //release lock and reacquires on wakeup
            System.out.println(Thread.currentThread() + " is woken up");
        }
        go = false; //resetting condition
    }
 
    /*
     * both shouldGo() and go() are locked on current object referenced by "this" keyword
     */

    private synchronized void go() {
        while (go == false){
            System.out.println(Thread.currentThread()
            + " is going to notify all or one thread waiting on this object");

            go = true; //making condition true for waiting thread
            //notify(); // only one out of three waiting thread WT1, WT2,WT3 will woke up
            notifyAll(); // all waiting thread  WT1, WT2,WT3 will woke up
        }
     
    }
 
}

Output in case of using notify
Thread[WT1,5,main] is going to wait on this object
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] is going to wait on this object
Thread[NT1,5,main] is going to notify all or one thread waiting on this object
Thread[WT1,5,main] is woken up
Thread[NT1,5,main] finished Execution
Thread[WT1,5,main] finished Execution

Output in case of calling notifyAll
Thread[WT1,5,main] is going to wait on this object
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] is going to wait on this object
Thread[NT1,5,main] is going to notify all or one thread waiting on this object
Thread[WT2,5,main] is woken up
Thread[NT1,5,main] finished Execution
Thread[WT3,5,main] is woken up
Thread[WT3,5,main] is going to wait on this object
Thread[WT2,5,main] finished Execution
Thread[WT1,5,main] is woken up
Thread[WT1,5,main] is going to wait on this object

I strongly recommend to run this Java program and understand output produce by it and try to understand it. Theory should complement practical example and if you see any inconsistency than let us know or try to rectify it. Along with deadlock, race condition and thread-safety,  inter thread communication is one of the fundamental of concurrent programming in Java.

Summary
In short here are answers of questions on notify and notifyAll we have raised at the start of this tutorial:

Which thread will be notified if I use notify()?
No guaranteed,  ThreadScheduler will pick a random thread from pool of waiting thread on that monitor. What is guaranteed is that only one Thread will be notified.

How do I know how many threads are waiting, so that I can use notifyAll() ?
Its depend upon your application logic, while coding you need to think whether a piece of code can be run by multiple thread or not. A good example to understand inter-thread communication is implementing producer consumer pattern in Java.

How to call notify()?
Wait() and notify() method can only be called from synchronized method or block, you need to call notify method on object on which other threads are waiting.

What are these thread waiting for being notified etc.
Thread wait on some condition e.g. in producer consumer problem, producer thread wait if shared queue is full and consumer thread wait if shared queue is empty. Since multiple thread are working with a shared resource they communicate with each other using wait and notify method.

That’s all on What is difference between notify and notifyAll method in Java  and when to use notify vs notifyAll in Java. Now you should be able to understand and use notify and notifyAll method for inter-thread communication in your Java program.

No comments:

Post a Comment