wait(), notify() and notifyAll() in Java - A tutorial

By Jagan Viewed: 32383 times Emailed: 260 times Printed: 543 times Bookmark and Share



The use of the implicit monitors in Java objects is powerful, but you can achieve a more subtle level of control through inter-process communication. As you will see, this is especially easy in Java.

Multithreading replaces event loop programming by dividing your tasks into discrete and logical units. Threads also provide a secondary benefit: they do away with polling. Polling is usually implemented by a loop that is used to check some condition repeatedly. Once the condition is true, appropriate action is taken. This wastes CPU time. For example, consider the classic queuing problem, where one thread is producing some data and another is consuming it. To make the problem more interesting, suppose that the producer has to wait until the consumer is finished before it generates more data. In a polling system, the consumer would waste many CPU cycles while it
waited for the producer to produce. Once the producer was finished, it would start polling, wasting more CPU cycles waiting for the consumer to finish, and so on. Clearly, this situation is undesirable.

To avoid polling, Java includes an elegant interrocess communication mechanism via the wait( ), notify( ), and notifyAll( ) methods. These methods are implemented as final methods in Object, so all classes have them. All three methods can be called only from within a synchronized method. Although conceptually advanced from a computer science perspective, the rules for using these methods are actually quite simple:

  • wait( ) tells the calling thread to give up the monitor and go to sleep until some other
    thread enters the same monitor and calls notify( ).
  • notify( ) wakes up the first thread that called wait( ) on the same object.
  • notifyAll( ) wakes up all the threads that called wait( ) on the same object. The
    highest priority thread will run first.

These methods are declared within Object, as shown here:

final void wait( ) throws InterruptedException
final void notify( )
final void notifyAll( )

Additional forms of wait( ) exist that allow you to specify a period of time to wait. The following sample program incorrectly implements a simple form of the producer/consumer problem. It consists of four classes: Q, the queue that you're trying to synchronize; Producer, the threaded object that is producing queue entries; Consumer, the threaded object that is consuming queue entries; and PC, the tiny class that creates the single Q, Producer, and Consumer.

// An incorrect implementation of a producer and consumer.
class Q {
int n;
synchronized int get() {
System.out.println("Got: " + n);
return n;
}
synchronized void put(int n) {
this.n = n;
System.out.println("Put: " + n);
}
}

class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while(true) {
q.put(i++);
}
}
}

class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while(true) {
q.get();
}
}
}

class PC {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}

Although the put( ) and get( ) methods on Q are synchronized, nothing stops the producer from overrunning the consumer, nor will anything stop the consumer from consuming the same queue value twice. Thus, you get the erroneous output shown here (the exact output will vary with processor speed and task load):

Put: 1
Got: 1
Got: 1
Got: 1
Got: 1
Got: 1
Put: 2
Put: 3
Put: 4
Put: 5
Put: 6
Put: 7
Got: 7

As you can see, after the producer put 1, the consumer started and got the same 1 five times in a row. Then, the producer resumed and produced 2 through 7 without letting the consumer have a chance to consume them.

The proper way to write this program in Java is to use wait( ) and notify( ) to signal in both directions, as shown here:

// A correct implementation of a producer and consumer.
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
if(!valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
if(valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}

class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while(true) {
q.put(i++);
}
}
}

class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while(true) {
q.get();
}
}
}

class PCFixed {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}

Inside get( ), wait( ) is called. This causes its execution to suspend until the Producer notifies you that some data is ready. When this happens, execution inside get( ) resumes. After the data has been obtained, get( ) calls notify( ). This tells Producer that it is okay to put more data in the queue. Inside put( ), wait( ) suspends execution until the Consumer has removed the item from the queue. When execution resumes, the next item of data is put in the queue, and notify( ) is called. This tells the Consumer that it should now remove it.

Here is some output from this program, which shows the clean synchronous behavior:

Put: 1
Got: 1
Put: 2
Got: 2
Put: 3
Got: 3
Put: 4
Got: 4
Put: 5
Got: 5

This tutorial is an extract from the book "The complete Reference Java 2" by Herbert Schildt




Comments(31)


1. Thanks for the article. I got some clearance now. Thank you again.

By: Reddy at 2008-03-15 00:02:17
2. nice article, many thanx :)

By: Unknown at 2008-10-16 21:09:02
3. very cool you said it! many thanks it's really cool 'n' clear

By: ArAsh at 2008-12-11 06:41:13
4. thank you. it was very useful.

By: ravindar at 2009-01-09 01:04:15
5. Great job!
Lot of things cleared...


By: alok at 2009-03-18 10:45:25
6. Good job!

By: jgui at 2009-04-22 10:54:54
7. i have clear that notify and wait
but where i have used the notifyAll
how can used and which situation we can used it
so have still some clearty

thanks
pp

By: pp at 2009-06-29 06:12:13
8. notify does NOT wake up the first thread waiting. it wakes up an abitrary thread waiting. notifyAll is almost always better than notify. A thread woken up by wait still has to compete with all other threads that are trying to lock on the object.

cheers
Armin

By: Armin at 2009-07-26 07:25:09
9. good example need some more explanation on notify all

By: prashant at 2009-09-08 19:29:54
10. Good example...easy to read and understand...

By: Codventure at 2009-09-11 00:07:06
11. Its a nice article obviously. Can you put something about asserstion. Hope it will be such a nice tutorial like this.


By: kowser at 2009-10-06 23:44:52
12. Hi. Useful article. Thanks

By: sheff at 2009-10-16 12:44:39
13. Great article. The simple example used easily makes the concept clear.

By: Nikhil at 2009-11-13 08:38:41
14. Marvelous Explanation. The whole concept is clear to me now

By: Rohit at 2009-12-01 19:43:14
15. Excellent!!!!! Thanks

By: nimbostratue at 2009-12-09 13:07:09
16. Good.understand

By: Selva at 2009-12-29 23:27:29
17. Very nice and easy to understand, keep it up !!

Cheers.

By: claudiu at 2010-02-07 06:12:30
18. is there a way to notify a specific thread?

By: bob at 2010-03-23 11:57:29
19. Really a great article!
I have some questions/suggestions:
Shouldn't be the wait-calls be inside a loop to account for spurious wakeups? (see http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#wait())
Also, I would put the rest of the code after the wait() also into the try-block, because i wouldn't want it to be executed after an InterruptedException.

By: ron at 2010-03-30 01:37:12
20. Very good. I like this way. First provide quite wrong implementation and then correct it. Its really good example. Thanks!

By: NJ at 2010-04-01 23:27:44
21. Very cool one, thanks, got the concept clear

By: black boot at 2010-04-18 08:20:20
22. Does Wait() inside synchronized create a race condition?

By: Aviator168 at 2010-04-21 16:02:06
23. Nice article, Thank you

By: kumar kasimala at 2010-04-26 21:09:25
24. Very nice article.. thanks

By: Basu at 2010-05-29 05:52:00
25. I have one doubt regarding this code,
if the producer thread is already synchronized on 'this' how does the consumer can enter get method which is again synchronized on 'this'.
And also in general i want to know why is wait(),notify() and notifyAll() are there in Object class.

By: Yellappa at 2010-06-11 05:49:15
26. Great!

By: sunil at 2010-06-13 12:32:09
27. Hello,

your solution is kinda overkill.
When used correctly, notify and wait don't need workarounds such as valueSet.

Here's the improved version:
----------------------
package producer;

// A correct implementation of a producer and consumer.
class Q {
int n;

synchronized int get() {
try {
notify();
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
return n;
}

synchronized void put(int n) {
try {
notify();
wait();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
System.out.println("Put: " + n);
}
}

public class Producer implements Runnable {
Q q;

Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}

public void run() {
int i = 0;
while (true) {
q.put(i++);
}
}
}

class Consumer implements Runnable {
Q q;

Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}

public void run() {
while (true) {
q.get();
}
}
}

class PCFixed {
public static void main(String args[]) {
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}

-------------------------

By: Hdm-Student at 2010-06-16 08:10:51
28. Explanations and examples are more clear. I like it.

By: Rajkumar S at 2010-07-12 22:28:40
29. 27: What happens if the producer and the customer enterin the wait at same time? Deadlock? I think no protection against deadlock.

By: Spender at 2010-07-25 14:42:08
30. Excellent Example to explain the functions

By: manish at 2010-08-05 03:10:43
31. Thanks mate !!!

-- Anish Sneh

By: Anish Sneh at 2010-08-18 07:42:56

Your name (required):


Your email(required, will not be shown to the public):


Your sites URL (optional):


Your comments:


Enter Code:
The Captcha image

Latest Tutorials

[2010-09-02]Steps in using verisign certificate with Glassfish appserver
[2010-08-02]emulator 0 terminated while waiting for it to register!
[2010-08-02]Cannot run program "C:\Program Files\Java\jre6\bin\javac.exe": CreateProcess error=2, The system cannot find the file specified
[2010-08-01]Step by Step guide to setup freetts for Java
[2010-07-31]Speech Packages available for Java API
[2010-07-31]Tutorial on setting up freetts with maven
[2010-07-31]package com.sun.speech.freetts does not exist.
[2010-07-31]Text to Speech conversion program in Java
[2010-07-31]How to create wav file using freetts
[2010-07-31]How to set the width of a Text element in JavaFX?
[2010-07-31]Major components of FxObjects in JavaFX
[2010-07-03]Using the AWS SDK for Java in Eclipse
[2010-07-03]Using the AWS SDK for Java
[2010-01-01]Converting properties using PropertyEditors and Other Spring features worth mentioning
[2010-01-01]How to create an array and method in JSP

More Latest News

Most Viewed Articles (in last 30 days)
How to use ArrayList in Java
XML and Java - Parsing XML using Java Tutorial
How to use Iterator in Java
How to Send SMS using Java Program (full code sample included)
Using substring( ) in Java
indexOf( ) and lastIndexOf( ) in Java
FileReader and FileWriter example program in Java
Using StringTokenizer in Java
HashMap example in Java
wait(), notify() and notifyAll() in Java - A tutorial
Method Overloading (function overloading) in Java
Abstract classes in Java
Method Overriding in Java
Transient vs Volatile modifiers in Java
compareTo( ) in Java
Most Emailed Articles (in last 30 days)
Components of program
How to Send SMS using Java Program (full code sample included)
XML and Java - Parsing XML using Java Tutorial
Why java is important to the Internet
How to use ArrayList in Java
Execute system commands in a Java Program
FileReader and FileWriter example program in Java
Recursion in java
indexOf( ) and lastIndexOf( ) in Java
What is Java?
Method Overloading (function overloading) in Java
Sample Java Script that displays a movable clock
compareTo( ) in Java
History of Object
How to use Iterator in Java