Java 中 wait 与 sleep 的区别

更新于 2025-12-29

baeldung 2024-01-08

1. 概述

在本文中,我们将简要介绍 Java 核心库中的标准 sleep()wait() 方法,并理解它们之间的异同。

2. wait 与 sleep 的主要区别

简单来说,wait() 是一个用于线程同步的实例方法

它可以在任意对象上调用(因为它定义在 java.lang.Object 类中),但只能在同步代码块(synchronized block)中调用。调用 wait()释放该对象上的锁,以便其他线程可以获取该锁并继续执行。

另一方面,Thread.sleep() 是一个静态方法,可以在任何上下文中调用。Thread.sleep() 暂停当前线程的执行,但不会释放任何已持有的锁

下面是一个非常简单的示例,展示了这两个核心 API 的基本用法:

private static Object LOCK = new Object();

private static void sleepWaitExamples() throws InterruptedException {
    Thread.sleep(1000);
    System.out.println(
      "线程 '" + Thread.currentThread().getName() +
      "' 在休眠 1 秒后被唤醒");

    synchronized (LOCK) {
        LOCK.wait(1000);
        System.out.println("对象 '" + LOCK + "' 在等待 1 秒后被唤醒");
    }
}

运行上述示例将产生如下输出:

线程 ‘main’ 在休眠 1 秒后被唤醒
对象 ‘java.lang.Object@31befd9f’ 在等待 1 秒后被唤醒

3. 唤醒 wait 与 sleep

当我们使用 sleep() 方法时,线程会在指定的时间间隔后自动恢复运行,除非在此期间被中断(interrupted)。

wait() 的唤醒机制则稍微复杂一些。我们可以通过在所等待的监视器(monitor)上调用 notify()notifyAll() 方法来唤醒处于等待状态的线程。

  • 如果希望唤醒所有处于等待状态的线程,请使用 notifyAll()
  • wait() 方法本身一样,notify()notifyAll()必须在同步上下文中调用

例如,以下是如何使用 wait() 等待另一个线程完成操作:

synchronized (b) {
    while (b.sum == 0) {
        System.out.println("等待 ThreadB 完成...");
        b.wait();
    }

    System.out.println("ThreadB 已完成。该线程计算的总和为: " + b.sum);
}

然后,另一个线程可以通过在其监视器上调用 notify() 来唤醒等待的线程:

int sum;

@Override 
public void run() {
    synchronized (this) {
        int i = 0;
        while (i < 100000) {
            sum += i;
            i++; 
        }
        notify(); 
    } 
}

运行此示例将产生如下输出:

等待 ThreadB 完成…
ThreadB 已完成。该线程计算的总和为: 704982704

4. 结论

本文简要介绍了 Java 中 waitsleep 的语义和使用场景。

  • 通常情况下,应使用 sleep() 来控制单个线程的执行时间
  • wait() 则用于多线程之间的协作与同步

当然,关于线程同步还有更多内容值得深入探索——但在深入之前,扎实掌握这些基础知识至关重要。