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
Category >> Concurrency  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • pl4za

    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();
    }
    }
    }

  • Rahul

    Why we should always call wait method in loop

  • Angelina Lawrence

    know how to you satisfy yahoo offer us an case in point of a accurate instance 1 by means of Runnable?

  • Sergey Zaytsev

    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.

  • TSMX

    Can you please provide us an example of a correct Example 1 using Runnable?

  • Ries van Twisk

    Yes, you can try this example and once a while it will lock up.

  • Vijay Shankar

    > 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();

    }

    }

  • Darragh

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

  • this is perfect for example #1 to understand more on wait()

  • vasanthjegathesan

    Quick hack: In that case, we can avoid wait “forever” with “b.wait(someTime)”.

  • call to wait() method should be with in a loop that checks the condition on which the thread is waiting. That’s a recommendation as per java docs to avoid a scenario known as spurious wakeup.

    Read more about it here – http://netjs.blogspot.com/2015/07/inter-thread-communiction-wait-notify-java-multi-thread.html

  • Ai

    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 ?

  • hrkristiansen

    “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”.

  • Ankit

    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

  • Pingback: Java 2 OCPJP – Threads | TinoChan()

  • Pingback: efttappingtechniques.com()

  • Pingback: 监听器-java同步的基本思想 | 并发编程网 - ifeve.com()

  • ash

    nope – UR right on a closer look.

  • Ash

    “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.

  • try this one

    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();

    }

    }

    }

    }

  • Amatya

    what is the name of second program..before psvm their should be a class name.

  • Amatya

    what is the name of second program..before psvm their should be a class name…

  • Pingback: 免费Simple Java (非常简单的英文) - IT新闻()

  • Pingback: 免费Simple Java (非常简单的英文) | | Evolution Unit 进化Evolution Unit 进化()

  • snamiet

    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?

  • Stech

    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.

  • hrkristiansen

    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.

  • Thanks. I knew that the answer is a piece of cake

  • ICF

    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

  • cadmy

    Sorry for damn question but why the result of the first example is 4950? How did it happen?

  • 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.

  • Guest

    Vishal

  • Guest

    asdasd

  • Santhosh S

    Thank you for the information.

  • maqsoodkhan

    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…

  • Igor

    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();

    }

    }

    }

  • Igor

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

  • Krzysiek

    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…

  • Great code example.I want to add that while wait method is present in the object class, sleep method is present in the Thread class. This means that we can’t invoke sleep() method on any object. Some beginners don’t understand the locking mechanism used by wait and sleep methods in java