Java Thread: notify() and wait() examples

This article contains two code examples to demonstrate Java concurrency. They stand for very typical usage. By understanding them, you will have a better understanding about notify() and wait().

1. Some background knowledge

  1. synchronized keyword is used for exclusive accessing.
  2. To make a method synchronized, simply add the synchronized keyword to its declaration. Then no two invocations of synchronized methods on the same object can interleave with each other.
  3. Synchronized statements must specify the object that provides the intrinsic lock. When synchronized(this) is used, you have to avoid to synchronizing invocations of other objects’ methods.
  4. 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( ).
  5. notify() wakes up the first thread that called wait() on the same object.

2. notify() and wait() – example 1

public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();
 
        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
 
            System.out.println("Total is: " + b.total);
        }
    }
}
 
class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

In the example above, an object, b, is synchronized. b completes the calculation before Main thread outputs its total value.

Output:

Waiting for b to complete...
Total is: 4950

If b is not synchonized like the code below:

public class ThreadA {
	public static void main(String[] args) {
		ThreadB b = new ThreadB();
		b.start();
 
		System.out.println("Total is: " + b.total);
 
	}
}
 
class ThreadB extends Thread {
	int total;
 
	@Override
	public void run() {
		for (int i = 0; i < 100; i++) {
			total += i;
		}
	}
}

The result would be 0, 10, etc. Because sum is not finished before it is used.

3. notify() and wait() – example 2

The second example is more complex, see the comments.

import java.util.Vector;
 
class Producer extends Thread {
 
    static final int MAXQUEUE = 5;
    private Vector messages = new Vector();
 
    @Override
    public void run() {
        try {
            while (true) {
                putMessage();
                //sleep(5000);
            }
        } catch (InterruptedException e) {
        }
    }
 
    private synchronized void putMessage() throws InterruptedException {
        while (messages.size() == MAXQUEUE) {
            wait();
        }
        messages.addElement(new java.util.Date().toString());
        System.out.println("put message");
        notify();
        //Later, when the necessary event happens, the thread that is running it calls notify() from a block synchronized on the same object.
    }
 
    // Called by Consumer
    public synchronized String getMessage() throws InterruptedException {
        notify();
        while (messages.size() == 0) {
            wait();//By executing wait() from a synchronized block, a thread gives up its hold on the lock and goes to sleep.
        }
        String message = (String) messages.firstElement();
        messages.removeElement(message);
        return message;
    }
}
 
class Consumer extends Thread {
 
    Producer producer;
 
    Consumer(Producer p) {
        producer = p;
    }
 
    @Override
    public void run() {
        try {
            while (true) {
                String message = producer.getMessage();
                System.out.println("Got message: " + message);
                //sleep(200);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
    public static void main(String args[]) {
        Producer producer = new Producer();
        producer.start();
        new Consumer(producer).start();
    }
}

A possible output sequence:

Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
put message
put message
put message
put message
put message
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011
Got message: Fri Dec 02 21:37:21 EST 2011

48 thoughts on “Java Thread: notify() and wait() examples”

  1. in example 1 : if the object is another type of object(another class or user defined object) it works well.But in this example thread is used so we can’t say when the thread executes . wait function may be executed before or after the thread calls its depends on system speed. So here we cant use threads if u use threads u can use these methods thread.isAlive(),thread.join() and thread.isDaemon() for checking the thread executed or running.

  2. Example#1 is really bad example. If `notify()` invokes before `b.wait()`, then you get a deadlock.

  3. Because Main thread itself gets ‘Blocked on Monitor’ and So, there is no thread to start the b thread.

  4. Hello friends!
    I am an official representative of private company which deals with all kinds of written work (essay, coursework, dissertation, presentation, report, etc) in short time.
    We are ready to offer a free accomplishment of written work hoping for further cooperation and honest feedback about our service.
    Send your work topics to our email: [email protected]. This offer has limited quantities!!!

  5. Can somebody please explain why in example 1, if I move b.start(); to below the synchronized(b) block, the output is always “Waiting for b to complete…”?

    synchronized(b){
    try{
    System.out.println(“Waiting for b to complete…”);
    b.wait();
    } catch(InterruptedException e){
    e.printStackTrace();
    }
    System.out.println(“Total is: ” + b.total);
    }
    b.start();

    Output: “Waiting for b to complete…”

    SInce b.wait() inside the block would release the lock and wait, why didn’t the program continue with b.start() and complete, so that the block can continue?

  6. My take on the first example. Added a sleep to simulate a notify too before the wait and a condition check to avoid thread lock:

    public class ThreadA {
    public static void main(String[] args){
    ThreadB b = new ThreadB();
    b.start();
    try {
    Thread.sleep(1000); // simulate a notify() before the wait()
    }
    catch (InterruptedException e) {

    }
    synchronized(b){
    try{
    System.out.println(“Waiting for b to complete…”);
    while (b.isAlive()) { //condition guarantees no thread lock occurs
    b.wait();
    }
    }catch(InterruptedException e){
    e.printStackTrace();
    }

    System.out.println(“Total is: ” + b.total);
    }
    }
    }

    class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
    synchronized(this){
    for(int i=0; i<100 ; i++){
    total += i;
    }
    notify();
    }
    }
    }

  7. It looks like in example#2 code in getMessage() is broken… notify() method call is too early which’ll wake up thread(s) already in m’s waitSet ( which exactly is thread called putMessage() ). notify() should be places at the end of getMessage() method.

  8. > Below is example of wait notify 1st customer is trying to withdrawal
    > money 2000 but account is having only 1000 Rs so wait for deposit,
    > once deposit is completed then customer will able to withdrawal
    > amount ..till deposit customer is waiting.

    package com.thread.example;

    class Cust{

    private int totalAmount=1000;

    public synchronized void withdrwl(int amount){
    System.out.println(“Total amount “+totalAmount +” withdrwling amount “+amount);
    if(this.totalAmount<amount){
    System.out.println("not enogh amount..waiting for deposite..");
    try{wait();}catch(Exception e){}
    }
    this.totalAmount-=amount;
    System.out.println("Withrawl successful..Remaining balance is "+totalAmount);

    }

    public synchronized void deposite(int amount){
    System.out.println("Depositing amount "+amount);
    this.totalAmount+=amount;
    System.out.println("deposit completed…and Now totalAmount is "+this.totalAmount);
    notify();
    }
    }

    class Depo implements Runnable{
    Cust c; int depo;
    Depo(Cust c, int depo){
    this.c=c;
    this.depo=depo;

    }

    @Override
    public void run() {
    c.deposite(depo);

    }

    }
    class Withdrawl implements Runnable{
    Cust c; int with;
    Withdrawl(Cust c, int with){
    this.c=c;
    this.with=with;

    }

    @Override
    public void run() {
    c.withdrwl(with);

    }

    }

    public class MainClass {

    public static void main(String[] args) {
    Cust c = new Cust();
    Thread w = new Thread(new Withdrawl(c, 2000));
    Thread d= new Thread(new Depo(c, 1000));
    w.start();
    d.start();

    }

    }

  9. I agree. You should use b.join(); which will force the main thread to wait until the calculation is complete

  10. This example won’t work if notify() is called before wait() is called . If it is the case, then main thread will wait/block forever . To make sure wait() is called 1st then before b.start() , we issue wait() command . Am I right ?

  11. “b.wait()” will cause the current thread (i.e. the main thread) to wait until another thread has called one of the notify-methods of “b”. Since no other thread has access to “b”, other than “b” itself, the main thread will wait “forever”.

  12. Looks fine form me ,
    main thread will start, then thread b will start and get the lock then completes its calculation. After that second block of synchronization will start and after printing “waiting for the thread b to complete….” it will call .wait() method to release the lock. Then again normal main thread will execute and prints the total.
    But I wanted a more complex example so that we can understand more . This is very simple example and not elaborating much

  13. “It only works if the main thread gets the hold of the monitor for ‘b’ before ‘b’ itself does.”
    I don’t see how this is true.
    b.start(); is starting b before main thread gets its lock
    b finishes its execution, gets into TERMINATED state and releases its lock
    main thread acquires b’s lock and gets into the synch’d block
    reads the value total and prints it out.

  14. package com.scjp.thread;

    import java.util.LinkedList;

    import java.util.List;

    import java.util.Queue;

    public class SychModification {

    public static void main(String[] args) {

    LinkedList linkedList = new LinkedList();

    AddItem addItem = new AddItem(linkedList, “Adding Thread”);

    AddItem addItem1 = new AddItem(linkedList, “Adding Thread1”);

    // AddItem addItem2 = new AddItem(linkedList, “Adding Thread2”);

    RemoveItem removeItem = new RemoveItem(linkedList,

    “Removing Item Thread”);

    removeItem.start();

    addItem.start();

    addItem1.start();

    // addItem2.start();

    }

    }

    class AddItem extends Thread {

    private List list;

    private static int count = 0;

    public AddItem(List list, String name) {

    super(name);

    this.list = list;

    }

    @Override

    public void run() {

    while (true) {

    try {

    synchronized (list) {

    System.out.println(“Adding value from ” + getName());

    list.add(“Add ITEM” + count++);

    list.notifyAll();

    }

    Thread.sleep(5000);

    } catch (InterruptedException ex) {

    ex.printStackTrace();

    }

    }

    }

    }

    class RemoveItem extends Thread {

    private List list;

    public RemoveItem(List list, String name) {

    super(name);

    this.list = list;

    }

    @Override

    public void run() {

    while (true) {

    try {

    synchronized (list) {

    list.wait();

    if(!list.isEmpty())

    System.out.println(((Queue) list).remove());

    System.out.println(list.size());

    }

    } catch (InterruptedException ex) {

    ex.printStackTrace();

    }

    }

    }

    }

  15. Can anyone explain why this program is getting stopped..

    public class ThreadA {

    public static void main(String[] args){

    ThreadB b = new ThreadB();

    b.setName(“ThreadB”);

    System.out.println(Thread.currentThread().getName()+” 1 “+b.getState());

    b.start();

    try {

    b.join();

    } catch (InterruptedException e1) {

    // TODO Auto-generated catch block

    e1.printStackTrace();

    }

    System.out.println(Thread.currentThread().getName()+” 2 “+b.getState());

    synchronized(b){

    try{

    System.out.println(“Waiting for b to complete…”);

    System.out.println(Thread.currentThread().getName()+” 3 “+b.getState());

    b.wait();

    System.out.println(Thread.currentThread().getName()+” 4 “+b.getState());

    }catch(InterruptedException e){

    e.printStackTrace();

    }

    }

    // System.out.println(“C Total is: ” + c.total);

    System.out.println(“B Total is: ” + b.total);

    System.out.println(Thread.currentThread().getName()+” 5 “+b.getState());

    }

    }

    class ThreadB extends Thread{

    int total;

    @Override

    public void run(){

    synchronized(this){

    for(int i=0; i<100 ; i++){

    total += i;

    }

    this.notify();

    System.out.println(Thread.currentThread().getName()+" run 3 "+getState());

    }

    }

    }

    Output:

    main 1 NEW

    Thread-0 run 3 RUNNABLE

    main 2 TERMINATED

    Waiting for b to complete…

    main 3 TERMINATED

    —————————-
    Program is still running but it doesn't get end.
    Is it a deadlock?

  16. Easier way to see that is to devide the numbers to pairs in this way:
    (1+99)+(2+98)….+(49+51)+50=49*(100)+50. Just an anakdote i hope you like.

  17. Example 1 is an absolutely hideous example of programming by coincidence: http://pragprog.com/the-pragmatic-programmer/extracts/coincidence

    It only works if the main thread gets the hold of the monitor for ‘b’ before ‘b’ itself does.

    The only way to assure this, is to make ThreadB implement Runnable (or use it as the one it already is) and then run it from a thread started from inside the ‘synchronized(b) { … }’ statement.

  18. int i = 0; i < 100… this means the range of numbers [0,99]. If you add those numbers together you get 4950…. using the formula N(N+1)/2 where N is your largest number in this case 99
    99(99+1)/2 = 4950

  19. When you have to extend some other class and still use multithreading then you can use implements runnable as in java you wont be able to extend two classes at the same time.

  20. I have doubt on threads can u tell me please when I have to use extends threads and implements and what is the difference between…

  21. Modified first program:

    public class ThreadA

    {

    public static void main(String[] args) throws InterruptedException

    {

    ThreadB b = new ThreadB();

    b.start();

    // Thread.sleep(500);

    if(!b.finished)

    synchronized (b)

    {

    try

    {

    System.out.println(“Waiting for b to complete…”);

    b.wait();

    }

    catch (InterruptedException e)

    {

    e.printStackTrace();

    }

    }

    System.out.println(“Total is: ” + b.total);

    }

    }

    class ThreadB extends Thread

    {

    int total;

    boolean finished;

    @Override

    public void run()

    {

    synchronized (this)

    {

    for (int i = 0; i < 100; i++)

    {

    total += i;

    }

    finished = true;

    notify();

    }

    }

    }

  22. Totally agree, before call to b.wait() there should be a check that will verify whether ThreadB completed its execution.

  23. If ThreadB be will aquire the lock before threadA then notify() will be called before wait() method. Then ThreadB will release the lock and we enter in synchronized block of ThreadA – wait() method will be called and program will hang cause notify() was already called before…

Leave a Comment