Kamis, 29 Mei 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.



























Source:http://javarevisited.blogspot.com/2012/10/difference-between-notify-and-notifyall-java-example.html

Tidak ada komentar:

Posting Komentar