← Back to Multithreading Course

PART 4 · CLASS 20

sleep() vs. wait()

Both sleep() and wait() can pause a thread. But they behave differently, especially when it comes to releasing locks. Let's understand the difference with simple examples.

1. A Quick Introduction

In our previous classes, we learned about two important methods:

  • sleep() — pauses a thread for a specified time.
  • wait() — makes a thread wait until another thread notifies it, or until it otherwise wakes up.

Both methods can make a thread stop executing temporarily. However, they serve different purposes.

Let's understand them one by one.

2. Understanding sleep()

The sleep() method belongs to the Thread class.

It pauses the execution of the currently running thread for a specified amount of time.

For example:

public class Main {

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

        System.out.println("Before sleeping");

        Thread.sleep(2000);

        System.out.println("After sleeping");
    }
}

Here, the main thread pauses for approximately two seconds.

The output will be:

Before sleeping
After sleeping

Notice that we called Thread.sleep(2000). The value is in milliseconds, so 2000 milliseconds means two seconds.

One important thing to remember: sleep() does not release any monitor locks that the thread is holding.

3. Understanding wait()

The wait() method belongs to the Object class.

It is used when a thread needs to wait for another thread to communicate with it.

When a thread calls wait() on an object, it releases that object's monitor lock and enters the waiting state.

It can wake up when another thread calls notify() or notifyAll() on the same object.

It can also wake up because of interruption, a spurious wakeup, or a timeout if a timed wait is used.

Remember that wait() must be called while the current thread owns the monitor lock of that object.

For example:

class SharedResource {

    public synchronized void waitForSignal()
            throws InterruptedException {

        System.out.println("Thread is waiting...");

        wait();

        System.out.println("Thread resumed!");
    }

    public synchronized void sendSignal() {

        System.out.println("Sending notification...");

        notify();
    }
}

Here, one thread can call waitForSignal() and another thread can call sendSignal().

The waiting thread releases the object's monitor when it calls wait(). The notifying thread can then acquire that lock, send the notification and eventually release the lock.

4. The Most Important Difference: Lock Release

This is the most important difference between sleep() and wait().

Imagine a thread is executing a synchronized method. It has acquired the object's monitor lock.

Now, suppose it pauses its execution.

What happens to the lock depends on which method it uses.

When a thread calls sleep()

  • The thread pauses for the specified time.
  • It continues holding any monitor locks it already owns.
  • Another thread cannot acquire those same locks until they are released.

When a thread calls wait()

  • The thread enters the waiting state.
  • It releases the monitor lock of the object on which wait() was called.
  • Another thread can acquire that object's monitor lock.
  • The waiting thread must reacquire the lock before continuing.

Remember: wait() releases only the monitor lock of the object on which it is called. It does not automatically release other locks held by the thread.

5. Let's Understand the Difference with an Example

Let's first see what happens when a thread uses sleep() inside a synchronized method.

class SharedResource {

    public synchronized void useResource() {

        System.out.println(
            Thread.currentThread().getName()
            + " acquired the lock"
        );

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return;
        }

        System.out.println(
            Thread.currentThread().getName()
            + " finished using the resource"
        );
    }
}

public class Main {

    public static void main(String[] args) {

        SharedResource resource = new SharedResource();

        Thread t1 = new Thread(
            resource::useResource, "Thread-1"
        );

        Thread t2 = new Thread(
            resource::useResource, "Thread-2"
        );

        t1.start();
        t2.start();
    }
}

Both threads are trying to execute the same synchronized method on the same object.

What happens?

  1. Thread-1 acquires the object's lock.
  2. Thread-1 calls sleep() for two seconds.
  3. Thread-1 pauses but continues holding the lock.
  4. Thread-2 cannot enter the synchronized method yet.
  5. Thread-1 wakes up and finishes its work.
  6. Thread-1 releases the lock when it exits the method.
  7. Thread-2 can now acquire the lock and execute the method.

This demonstrates that sleep() does not release the monitor lock.

6. Quick Comparison

Let's put everything together in one simple comparison.

Feature sleep() wait()
Belongs to Thread class Object class
Purpose Pause a thread for some time Wait for a condition or notification
Releases monitor lock? No Yes, the lock of the object on which wait() is called
How does it wake up? After the requested time, or earlier if interrupted Notification, interruption, spurious wakeup, or timeout
Must be called inside synchronized code? No Yes, while holding the object's monitor lock

7. When Should We Use Them?

Use sleep() when you simply want a thread to pause for a particular amount of time.

For example:

  • Pausing between repeated operations.
  • Creating a simple delay in a demonstration.
  • Simulating a time-consuming task in an example.

Use wait() when a thread needs to wait for another thread to change a shared condition or notify it.

For example:

  • A consumer waiting for data from a producer.
  • A thread waiting until a shared resource becomes available.
  • Threads coordinating their work.

We will explore one of these situations in detail in our upcoming Producer–Consumer classes.

Test Your Understanding

Let's see how well you understood this class!

Question 1: Which class provides the sleep() method?

Question 2: Which class provides the wait() method?

Question 3: What happens to the monitor lock when a thread calls sleep()?

Question 4: What happens when a thread calls wait() on an object?

Question 5: When should we use wait()?

Class Summary

Let's quickly revise what we learned today:

  • sleep() belongs to the Thread class.
  • wait() belongs to the Object class.
  • sleep() pauses a thread for a specified time.
  • wait() makes a thread wait for a condition or notification.
  • sleep() does not release monitor locks.
  • wait() releases the monitor lock of the object on which it is called.
  • A thread using wait() must reacquire that lock before continuing.

The most important difference to remember: sleep() pauses a thread without releasing its monitor locks, while wait() releases the monitor lock of the object on which it is called.

NEXT CLASS · CLASS 21

Understanding the Producer–Consumer Problem

Imagine one thread producing data while another thread consumes it. What happens if the consumer is ready but there is no data available? What if the producer creates data faster than the consumer can process it?

In our next class, we will understand this common multithreading problem using a simple real-world example.

0% Completed

You have completed 20 out of 46 classes.