“sleep和 wait都能让线程停下来,它俩到底有啥区别?”

如果你只回答:“一个是 Thread 类的方法,一个是 Object 类的方法”,那面试官大概率会觉得你只是背了八股文,并没有理解并发的核心。

今天咱们用**“占坑”**的例子,一次性把这两个方法的底层逻辑讲透。以后再被问到,直接把这个场景甩给面试官。


一、 核心区别:关键在于“锁” (Lock) 

这是最最最核心的区别,请刻在 DNA 里:

  • sleep (睡觉):是自私的。线程虽然停下来休息了,但是它手里的锁(Key)是不释放的

    • 潜台词:“我睡一会,但我占着茅坑不拉屎,外面的兄弟谁也别想进来。”

  • wait (等待):是无私的(或者说是被迫无奈)。线程停下来,会主动释放锁,进入等待队列。

    • 潜台词:“哎呀,我需要的条件(比如数据)还没准备好,我先把坑位让出来,你们先用,等条件好了(notify)再叫我。”

 场景模拟:试衣间

假设有一个试衣间(锁/Monitor),只有一把钥匙。

  1. sleep 的场景

    你拿着钥匙进了试衣间,锁上门。突然你想休息 5 分钟。于是你在里面睡着了

    • 后果:外面排队的人(其他线程)急死了,因为门是锁着的,谁也进不来。时间到了你自己醒了,继续试衣服,试完才出门。

  2. wait 的场景

    你拿着钥匙进了试衣间,锁上门。发现衣服尺码不对(条件不满足)。

    • 后果:你不能干占着位置啊。于是你开锁,走出门,坐在门口的小板凳上等(Wait Set)。这时候,别人(其他线程)就可以拿钥匙进试衣间了。等店员(另一个线程)拿来了新衣服,喊了一声“衣服到啦”(notify),你再去重新排队抢钥匙进门。


二、 来源不同:为什么 wait 定义在 Object 里?

这也是个经典追问。

  • Thread.sleep():它是 Thread 类的静态方法

    • 它是用来控制当前正在执行的线程的。它不需要依赖任何锁(Monitor),就是单纯的“让 CPU 休息一会”。

  • Object.wait():它是 Object 类的成员方法

    • 为什么不是 Thread 的方法? 因为 Java 中的锁(Monitor)是绑定在对象上的

    • 当你调用 lock.wait() 时,你是在操作这个 lock 对象上的等待队列。为了让任何对象都能成为锁,这个方法必须定义在基类 Object 中。


三、 使用限制:要不要 try-catch?要不要 synchronized?

1. 异常处理 (InterruptedException)

俩人都一样。不管是睡着了还是在等待,如果有人想暴力唤醒你(调用 interrupt()),它俩都会抛出 InterruptedException。所以都需要 try-catch

2. 同步代码块 (Synchronized)
  • sleep不需要。你想在哪睡就在哪睡,可以在客厅(同步块外),也可以在卧室(同步块内)。

  • wait必须在 synchronized 块中调用

    • 为什么? 回到第一点,wait 的前提是“释放锁”。如果你手里连锁都没有,你释放个寂寞?

    • 如果不加 synchronized 直接调用 wait,会抛出 IllegalMonitorStateException(非法监视器状态异常)。


四、 唤醒机制:谁来叫醒我?

  • sleep(long millis)自动醒

    • 你是定闹钟睡觉的。时间到了(比如 1000ms),你就会自动醒来,重新去抢 CPU 时间片。

  • wait()被动醒(如果不传超时时间)。

    • 你是“死等”。除非有别的线程调用了同一个锁对象的 notify()notifyAll(),否则你会一直等到天荒地老。

    • 注:wait(long timeout) 也可以设置超时自动醒,这点和 sleep 类似,但它依然需要先获取锁。


 总结:一张表看懂

特性 Thread.sleep() Object.wait()
所属类 Thread Object
对锁的处理 抱着锁睡觉(不释放) 放下锁等待(释放锁)
使用范围 任何地方 必须在 synchronized 块内
唤醒方式 时间到自动醒 需要 notify() / notifyAll()
核心用途 模拟延迟、暂停执行 线程间通信(生产/消费)

 最后的实战建议

  • 如果你只是想让程序“卡”一下,比如轮询的时候防止 CPU 空转,或者模拟网络延迟,请用 sleep

  • 如果你是做线程间通信,比如“生产者-消费者”模型,队列满了生产者要等,队列空了消费者要等,必须用 wait/notify(或者更高级的 Condition.await/signal)。

以后面试官再问,记住那句话:Sleep 是自私的占坑,Wait 是无私的让位。

Logo

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

更多推荐