Header javaperspective.com
JavaPerspective.com  >   Intermediate Tutorials  >   2. Concurrency  >   2.5. Wait and notify

2.5. Wait and notify
Last updated: 31 January 2013.

This tutorial will show you how and when to use the methods wait, notify and notifyAll.

In some situations, thread A may have to pause execution until thread B has finished executing certain statements. When B has finished executing those statements, it notifies A so that A can resume execution. To this end, the Java language provides the 3 following methods in the class Object:

These methods rely on a single monitor to work properly. For this reason, in order to use them the right way, you must follow two simple rules:
  1. The methods wait, notify and notifyAll must be called on the same object.
  2. A thread calling wait, notify or notifyAll on an object must first acquire that object's monitor, that is, these methods must be called within a synchronized method or a synchronized(this) block.

The following example shows a basic use of the methods wait and notify:

public final class Shared {

   
private boolean condition = false;

   
public synchronized void waitForNotification(){
         
while(! condition){
               
try{
                     
wait();
               
}
               
catch(InterruptedException e){

                }
          }

         
System.out.println("Resuming execution");
         
// execute other statements
          // ...
   
}

   
public synchronized void sendNotification(){
         
try{
               
Thread.sleep(5000);
         
}
         
catch(InterruptedException e){

          }

         
condition = true;
          notify
();
   
}

}

The class Shared contains a boolean (condition) and two methods: waitForNotification and sendNotification. Each method is supposed to be executed by a different thread on the same instance of the class Shared. Of course, both threads are also supposed to run at the same time. When a thread enters the method waitForNotification, it waits until it receives a notification from another thread executing the method sendNotification.

This is how it works: A thread that starts executing the synchronized method waitForNotification on an instance of the class Shared must acquire the monitor of that instance. After acquiring the monitor, the thread enters the while statement. If condition evaluates to false, the method wait is called. As a result, the monitor is released and the thread pauses execution.

Later on, another thread that starts executing the synchronized method sendNotification acquires the monitor, sleeps for 5 seconds, sets condition to true, calls the method notify and releases the monitor.

When the first thread receives that notification, it acquires the monitor again and wakes up (the method wait returns). At the next iteration of the while statement, since condition evaluates to true, the loop is exited and the thread resumes execution.

You might be wondering why a boolean (condition) is evaluated in a while statement enclosing the call to the method wait. In fact, this is the recommended way to use the method wait: within a while statement evaluating a certain condition. The condition is to ensure that the notification comes from the right thread. In this basic example, a notification can only come from a thread executing the method sendNotification. However, the class Shared could also contain another method (let's say sendNotification2) wherein notifyAll is invoked to send notifications to all the threads waiting in a method named waitForNotification2. Such notifications would also be received by threads waiting in waitForNotification. Hence, a thread that is waiting in waitForNotification may receive a notification from a thread executing sendNotification2 before receiving a notification from a thread executing sendNotification. Therefore, the boolean condition which is set to true in the method sendNotification ensures that the notification comes from a thread executing sendNotification.

The method wait is usually called in a try/catch block as I did above because an InterruptedException is thrown if another thread calls the method interrupt on a thread that is waiting. In the code above, you might have noticed that nothing is done in the catch block. Of course, if your program requires a specific handling of the InterruptedException, you are free to write code in the catch block. For example, you can write a return statement in the catch block so that the method waitForNotification simply returns.

In the following sample, the class MyThread1 calls the method waitForNotification:

public final class MyThread1 extends Thread {

   
private Shared shared;

   
public MyThread1(Shared shared){
         
this.shared = shared;
   
}

   
public void run(){
         
shared.waitForNotification();
   
}

}

On the other hand, the class MyThread2 calls the method sendNotification:

public final class MyThread2 extends Thread {

   
private Shared shared;

   
public MyThread2(Shared shared){
         
this.shared = shared;
   
}

   
public void run(){
         
shared.sendNotification();
   
}

}

Finally, the class App creates and starts an instance of the class MyThread1 and an instance of the class MyThread2. As you can see, a single instance of the class Shared is created and passed to the instances of MyThread1 and MyThread2:

public final class App {

   
public static void main(String[] args){
         
Shared shared = new Shared();

         
new MyThread1(shared).start();
         
new MyThread2(shared).start();
   
}

}

This is a basic example that shows how to use the methods wait and notify within synchronized methods. However, for more flexibility, you can call wait and notify within synchronized(this) blocks and thereby allow some statements to be executed concurrently before and after the synchronized(this) blocks. Furthermore, the method notify sends a notification to a single thread that is waiting. If you want to send a notification to all the threads that are waiting on the same monitor, you have to call the method notifyAll instead.


You are here :  JavaPerspective.com  >   Intermediate Tutorials  >   2. Concurrency  >   2.5. Wait and notify
Next tutorial :  JavaPerspective.com  >   Intermediate Tutorials  >   2. Concurrency  >   2.6. Daemon threads

Copyright © 2013. JavaPerspective.com. All rights reserved.  ( Terms | Contact | About ) 
Java is a trademark of Oracle Corporation
Image 1 Image 2 Image 3 Image 4 Image 5 Image 6 Image 7