在 Java 面试中,有一道非常经典的并发问题:

“sleep 和 wait 有什么区别?”

很多开发者的第一反应是:

  • sleep 是线程休眠
  • wait 是线程等待

如果只回答到这里,基本上是 不及格答案

因为面试官真正想考察的是:

  • 是否释放锁
  • 所属类不同
  • 使用场景
  • 唤醒机制
  • 线程通信原理

如果这些说不清楚,说明你对 Java 线程模型和并发机制 的理解还不够深入。

本文将通过 原理 + 代码 + 实战场景 带你彻底理解 sleepwait 的区别。

[外链图片转存中…(img-VREdu4TM-1773651856836)]


一、问题背景

在多线程编程中,我们经常会遇到这样的需求:

  • 线程暂停一段时间
  • 线程等待某个条件
  • 线程之间进行通信

Java 提供了两个常用方法:


Thread.sleep()
Object.wait()

很多开发者容易混淆这两个方法,因为它们都可以:

让线程进入阻塞状态。

但实际上:

两者在设计目的和底层机制上完全不同。

对比项 sleep wait
所属类 Thread Object
是否释放锁 不释放 释放
使用位置 任意位置 必须在 synchronized 中
唤醒方式 时间结束 notify / notifyAll
主要作用 线程暂停 线程通信

我整理了一套完整Java面试题库,
完整版在我的技术站。

https://myquotego.com/html/questions?_from=csdn_123_1

如果你准备 Java 面试,这类 并发高频问题一定要重点掌握


二、技术原理解析

理解 sleepwait,首先需要理解 Java 的 线程状态

Java 线程主要有以下状态:


NEW
RUNNABLE
BLOCKED
WAITING
TIMED_WAITING
TERMINATED

sleepwait 都会让线程进入阻塞状态,但进入的状态不同。


1 sleep 的原理

sleepThread 类中的静态方法:

Thread.sleep(long millis)

作用是:

让当前线程暂停指定时间。

底层原理:

RUNNABLE → TIMED_WAITING

时间结束后:

线程自动恢复运行。

重要特点:

  • 不会释放锁
  • 只是让 CPU 调度暂停

例如:

如果线程在 synchronized 中调用 sleep

其他线程仍然无法获取锁

因为锁仍然被当前线程持有。


2 wait 的原理

wait 方法属于 Object 类:

public final void wait()

设计目的是:

线程通信机制。

调用 wait 后:

RUNNABLE → WAITING

线程会:

  • 释放当前锁
  • 进入等待队列
  • 等待 notify() 唤醒

唤醒方式:

notify()
notifyAll()

重要特点:

  • 必须在 synchronized 中使用
  • 调用后会释放锁

这就是 waitsleep 的核心区别。


3 为什么 wait 在 Object 类中?

这是很多面试官喜欢问的问题。

原因是:

锁是对象级别的。

Java 中每个对象都有一个:

monitor(监视器锁)

线程在进入 synchronized 时:

会获取该对象的 monitor。

因此:

wait / notify 必须绑定对象

所以被设计在 Object 类中。


4 wait notify 的线程通信机制

线程通信流程:

线程A 获取锁
线程A 调用 wait
线程A 释放锁并等待

线程B 获取锁
线程B 修改条件
线程B 调用 notify

线程A 被唤醒
线程A 重新获取锁继续执行

这个机制在很多并发框架中都会使用。

我整理了一套完整Java面试题库,
完整版在我的技术站。

https://myquotego.com/html/questions?_from=csdn_123_1

如果系统学习 Java 面试,这类 线程通信问题出现频率非常高


三、代码示例

下面通过代码演示两者区别。


示例1:sleep 不释放锁

class SleepExample {

    public synchronized void test() {

        System.out.println(Thread.currentThread().getName() + " start");

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName() + " end");
    }

    public static void main(String[] args) {

        SleepExample example = new SleepExample();

        new Thread(example::test, "Thread-A").start();
        new Thread(example::test, "Thread-B").start();

    }
}

运行结果:

Thread-A start
(等待3秒)
Thread-A end
Thread-B start
Thread-B end

说明:

Thread-A sleep 时没有释放锁

Thread-B 必须等待。


示例2:wait 释放锁

class WaitExample {

    public synchronized void test() {

        System.out.println(Thread.currentThread().getName() + " start");

        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName() + " end");
    }

    public static void main(String[] args) {

        WaitExample example = new WaitExample();

        new Thread(example::test, "Thread-A").start();
        new Thread(example::test, "Thread-B").start();

    }
}

运行结果:

Thread-A start
Thread-B start

说明:

Thread-A wait 后释放锁
Thread-B 可以执行

示例3:wait + notify 通信

class ProducerConsumer {

    private final Object lock = new Object();
    private boolean ready = false;

    public void waitMethod() throws InterruptedException {

        synchronized (lock) {

            while (!ready) {
                lock.wait();
            }

            System.out.println("继续执行任务");
        }
    }

    public void notifyMethod() {

        synchronized (lock) {

            ready = true;
            lock.notify();

        }
    }
}

这个模式是:

经典生产者消费者模型基础。


Java面试题


四、实际应用场景

理解理论之后,更重要的是:

什么时候使用 sleep?什么时候使用 wait?


场景1:线程延迟执行

例如:

定时任务
重试机制
限流

通常使用:

Thread.sleep()

例如:

Thread.sleep(1000);

暂停 1 秒。


场景2:线程通信

例如:

生产者消费者
任务等待
资源协调

通常使用:

wait / notify

例如:

消息队列
线程池
阻塞队列

场景3:并发框架

在实际项目中,很多框架都基于:

wait / notify

例如:

BlockingQueue
线程池
线程协调器

不过在现代 Java 开发中,更推荐使用:

Lock
Condition
CountDownLatch
Semaphore

这些工具类位于:

java.util.concurrent

功能更强大,使用更安全。

我整理了一套完整Java面试题库,
完整版在我的技术站。

https://myquotego.com/html/questions?_from=csdn_123_1

如果准备 Java 面试,建议系统学习 并发编程核心知识


五、总结

最后总结 sleepwait 的核心区别。

对比项 sleep wait
所属类 Thread Object
是否释放锁 ❌ 不释放 ✅ 释放
使用位置 任意 synchronized 中
唤醒方式 时间结束 notify
线程状态 TIMED_WAITING WAITING
使用场景 延迟执行 线程通信

面试推荐标准回答:

sleep 是 Thread 类的方法,用于让线程暂停一段时间,不会释放锁;
wait 是 Object 类的方法,用于线程通信,必须在 synchronized 中使用,并且调用后会释放锁,需要通过 notify 或 notifyAll 唤醒。

如果能再结合 线程状态、monitor 机制、生产者消费者模型 进行解释,基本就是一个 满分答案


关注我,持续更新Java面试核心知识。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐