当前位置: 首页 > 工具软件 > Notify.js > 使用案例 >

Java: notify() vs. notifyAll()

狄心水
2023-12-01

Simply put, it depends on why your threads are waiting to be notified. Do you want to tell one of the waiting threads that something happened, or do you want to tell all of them at the same time?

In some cases, all waiting threads can take useful action once the wait finishes. An example would be a set of threads waiting for a certain task to finish; once the task has finished, all waiting threads can continue with their business. In such a case you would use notifyAll() to wake up all waiting threads at the same time.

Another case, for example mutually exclusive locking, only one of the waiting threads can do something useful after being notified (in this case acquire the lock). In such a case, you would rather use notify(). Properly implemented, you could use notifyAll() in this situation as well, but you would unnecessarily wake threads that can't do anything anyway.


notify vs notifyAll in Java

What is difference between notify and notifyAll method is one of the tricky Java question, which iseasy to answer but once Interviewer ask followup questions, you either gotconfused or not able to provide clear cut and to the point answers. Maindifference between notify and notifyAll is that notify methodwill only notify one Thread and notifyAll methodwill notify all Threads  which arewaiting on that monitor or lock. By the way this is something you have beenreading in all over places and to be frank, this statement despite being correct is not complete and its verydifficult to understand differencebetween notify vs notifyAll by just reading this statement. Lot of questionscomes 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 isincomplete without discussing wait method in Java and I had touched based onthis on my earlier article why wait and notify must be called fromsynchronized context. In order to get answer of those questions andunderstand difference between notify and notifyAll we will use a simple JavaThread example using wait and notify code :

Differencebetween notify and notifyAll in Java
Java provides two methods notify and notifyAll for wakingup threads waiting on some condition and you can use any of them but there issubtle difference between notify and notifyAll in Javawhich makes it one of the popular multi-threading interviewquestion in Java. When you call notify only oneof waiting thread will be woken and its not guaranteed which thread will bewoken, it depends upon Thread scheduler. While if you call notifyAll method, allthreads waiting on that lock will be woken up, but again all woken thread willfight for lock before executing remaining code and that's why wait is called onloop because if multiple threads are woken up, the thread which will get lockwill first execute and it may reset waiting condition, which will forcesubsequent threads to wait. So key differencebetween notify and notifyAll is that notify() will causeonly one thread to wake up while notifyAll method willmake all thread to wake up.


Whento use notify and notifyAll in Java
This is the follow-up question if you get pass the earlier one Difference between notifyAll andnotify in Java. If you understand notify vs notifyAll then youcan answer this by applying little common sense. You can use notify over notifyAll if allthread are waiting for same condition and only one Thread at a time can benefitfrom condition becoming true. In this case notify isoptimized call over notifyAll because waking up all of thembecause 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 looksquite reasonable there is still a caveat that unintended recipient swallowingcritical notification. by using notifyAll we ensurethat all recipient will get notify. Josh bloach has explained this in gooddetail in his book Effective Java , I highly recommend this book if you haven'tread them already. Another one you can try is Concurrency Practice in Java andJava Thread, which discusses wait and notify methods ingood details.

Example of notify and notifyAll method inJava

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

CodeExample of notify and notifyAll
Here is complete code example of How to use notify and notifyAll methodin Java. We have already explained when to use notify vs notifyAll method andthis example will clarify effect of calling notify and notifyAllmethod  in Java.

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

/**
 * Java program to demonstrate How to use notify and notifyAll methodin Java and
 * How notify and notifyAllmethod notifies thread, which thread gets woke up etc.
 */
public classNotificationTest {

    private volatile booleango = false ;

    public static voidmain ( String args []) throwsInterruptedException {
        finalNotificationTest test = newNotificationTest () ;
     
        Runnable waitTask = new Runnable (){
     
            @ Override
            publicvoid
run (){
                try {
                    test. shouldGo () ;
                } catch ( InterruptedException ex ) {
                    Logger. getLogger (NotificationTest. class. getName ()).
                           log ( Level. SEVERE, null,ex ) ;
                }
                System. out. println ( Thread. currentThread () + " finishedExecution" ) ;
            }
        } ;
     
        Runnable notifyTask = new Runnable (){
     
            @ Override
            publicvoid
run (){
                test. go () ;
                System. out. println ( Thread. currentThread () + " finishedExecution" ) ;
            }
        } ;
     
        Thread t1 = newThread (waitTask, "WT1" ) ; //will wait
        Thread t2 = newThread (waitTask, "WT2" ) ; //will wait
        Thread t3 = newThread (waitTask, "WT3" ) ; //will wait
        Thread t4 = newThread (notifyTask, "NT1" ) ; //will notify
     
        //starting allwaiting thread

        t1. start () ;
        t2. start () ;
        t3. start () ;
     
        //pause to ensureall waiting thread started successfully
        Thread. sleep ( 200 ) ;
     
        //starting notifyingthread
        t4. start () ;
     
    }
    /*
     * wait and notify can only be called from synchronizedmethod or bock
     */

    private synchronized voidshouldGo () throwsInterruptedException {
        while (go != true ){
            System. out. println ( Thread. currentThread ()
                         + " is going to wait on this object" ) ;
            wait () ; //release lockand reacquires on wakeup
            System. out. println ( Thread. currentThread () + " is wokenup" ) ;
        }
        go = false ; //resettingcondition
    }
 
    /*
     * both shouldGo() and go() are locked on current objectreferenced by "this" keyword
     */

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

            go = true ; //makingcondition true for waiting thread
            //notify();// only one out of three waiting thread WT1, WT2,WT3 will woke up

            notifyAll () ; // all waitingthread  WT1, WT2,WT3 will woke up
        }
     
    }
 
}

Output in caseof using notify
Thread
[WT1, 5,main ] is going to wait on thisobject
Thread [WT3, 5,main ] is going to wait on thisobject
Thread [WT2, 5,main ] is going to wait on thisobject
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 caseof calling notifyAll
Thread
[WT1, 5,main ] is going to wait on thisobject
Thread [WT3, 5,main ] is going to wait on thisobject
Thread [WT2, 5,main ] is going to wait on thisobject
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 thisobject
Thread [WT2, 5,main ] finished Execution
Thread [WT1, 5,main ] is woken up
Thread [WT1, 5,main ] is going to wait on thisobject

I strongly recommend to run this Java program and understand outputproduce by it and try to understand it. Theory should complement practicalexample 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 thefundamental of concurrent programming in Java.

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

Whichthread will be notified if I use notify()?
No guaranteed,  ThreadSchedulerwill 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 Iknow how many threads are waiting, so that I can use notifyAll() ?
Its depend upon your application logic, while coding you need to thinkwhether a piece of code can be run by multiple thread or not. A good example tounderstand inter-thread communication is implementing producer consumer pattern in Java.

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

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

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

 类似资料:

相关阅读

相关文章

相关问答