1. 概述

在这篇短文中,我们将探讨 Java 核心库中的标准 sleep()wait() 方法,并理解它们之间的差异和相似之处。

2. Wait 和 Sleep 的一般区别

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

它可以在任何对象上调用,因为它直接定义在 java.lang.Object 类上,但只能在同步块中调用。它会释放对象的锁,以便其他线程可以进入并获取锁。

另一方面,Thread.sleep() 是一个静态方法,可以从任何上下文调用。Thread.sleep() 暂停当前线程,但不释放任何锁。

下面是这两个核心 API 的简单使用示例:

private static Object LOCK = new Object();

private static void sleepWaitExamples() 
  throws InterruptedException {
 
    Thread.sleep(1000);
    System.out.println(
      "Thread '" + Thread.currentThread().getName() +
      "' is woken after sleeping for 1 second");
 
    synchronized (LOCK) {
        LOCK.wait(1000);
        System.out.println("Object '" + LOCK + "' is woken after" +
          " waiting for 1 second");
    }
}

运行这个示例将产生以下输出:

Thread 'main' is woken after sleeping for 1 second
Object 'java.lang.Object@31befd9f' is woken after waiting for 1 second

3. 唤醒 Wait 和 Sleep

当我们使用 sleep() 方法时,线程会在指定的时间间隔后启动,除非被中断。

对于 *wait()*,唤醒过程稍微复杂一些。我们可以通过在正在等待的监视器上调用 notify()notifyAll() 方法来唤醒线程。

当你想唤醒所有处于等待状态的线程时,使用 notifyAll() 而不是 notify()。与 wait() 方法本身类似,notify()notifyAll() 也必须在同步上下文中调用。

例如,这里是 wait 的使用方法:

synchronized (b) {
    while (b.sum == 0) {
        System.out.println("Waiting for ThreadB to complete...");
        b.wait();
    }

    System.out.println("ThreadB has completed. " + 
      "Sum from that thread is: " + b.sum);
}

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

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

运行这个示例将产生以下输出:

Waiting for ThreadB to complete…
ThreadB has completed. Sum from that thread is: 704982704

4. 总结

这是对 Java 中 waitsleep 语义的快速介绍。

通常,我们应该使用 sleep() 来控制单个线程的执行时间,而使用 wait() 来进行多线程同步。当然,在理解好基础知识之后,还有很多值得探索的内容。

一如既往,你可以在 GitHub 上查看本文提供的示例。


原始标题:Difference Between Wait and Sleep in Java