大家好,欢迎来到IT知识分享网。
从一道面试题看并发编程的”拦路虎”
“Wait 和 Sleep 有什么区别?”这道题是不是让你挠头? 就像餐厅等位时,有人占着座位玩手机(sleep()),有人把座位让给别人去候客区等叫号(wait())——看似都是”等”,但背后的逻辑天差地别!今天咱们用3个真实案例+2张对比表,把这对”孪生兄弟”彻底讲明白,让你面试再也不慌!
核心区别对比:6大维度吃透底层差异
一张表看懂核心差异 ⚠️

1. 所属类与调用方式
- wait():是Object类的方法(所有对象都有!),必须在synchronized同步块里调用,比如:
- synchronized(lock) { lock.wait(); // 正确姿势 }
- 要是敢在同步块外调用?立马给你抛IllegalMonitorStateException异常!
- sleep():是Thread类的静态方法,直接Thread.sleep(1000)就能用,不需要锁!
2. 锁处理机制:最核心的区别!
这是面试官最爱问的点!划重点:
- sleep():睡觉都抱着锁不放! 比如线程拿着锁睡1秒,其他线程只能干等着。
- wait():会主动释放锁,让其他线程有机会干活。就像上厕所要先出来才能让别人进~
3. 唤醒机制:被动通知 vs 主动起床 ⏰
- wait():得靠别人叫醒!要么其他线程调用notify(),要么等超时(比如wait(3000)等3秒)。
- sleep():到点自动醒,不需要别人管。适合定时任务,比如每小时刷新缓存。
4. 线程状态变化

- wait():进入WAITING状态,被唤醒后要重新抢锁
- sleep():进入TIMED_WAITING状态,醒了直接继续跑
使用场景深度解析:该用哪个?怎么选?
场景1:生产者-消费者模型(必须用wait()!)
比如电商订单系统,生产者(下单线程)和消费者(处理线程)要协作:
- 库存满了?生产者wait()释放锁,等消费者处理完再notify()唤醒
- 库存空了?消费者wait(),等生产者补货到了再唤醒

核心代码就5行:
synchronized(queue) { while(queue.isEmpty()) queue.wait(); // 没货就等 Object data = queue.poll(); queue.notifyAll(); // 通知生产者补货 }
场景2:定时任务(用sleep()更简单)⏲️
比如每30分钟刷新一次缓存,用sleep()一行搞定:
while(true) { refreshCache(); Thread.sleep(30*60*1000); // 睡30分钟 }
简单直接,不用处理复杂的锁机制~
3个实战坑点,90%的人都踩过!
坑点1:用if判断条件(虚假唤醒问题)
错误示范:
if(queue.isEmpty()) { // 千万别用if! queue.wait(); }
正确做法是用while循环:
while(queue.isEmpty()) { // 循环检查,防止假唤醒 queue.wait(); }
因为线程可能被”虚假唤醒”(操作系统的bug),必须再检查一遍条件!
坑点2:捕获异常后不恢复中断状态
try { Thread.sleep(1000); } catch (InterruptedException e) { // 必须加这句!否则上层代码不知道被中断了 Thread.currentThread().interrupt(); }
坑点3:wait和notify用了不同的锁对象
// 错误示范! synchronized(lock1) { lock1.wait(); } // 等lock1的通知 synchronized(lock2) { lock2.notify(); } // 却通知lock2的线程
记住:必须用同一个锁对象!就像你在A群@人,那人得在A群才能收到~
大厂真实案例:这俩方法怎么用?
案例1:阿里电商订单系统
双11高峰期,用wait()实现订单队列削峰:
- 订单太多处理不过来?让生产者线程wait()
- 消费者处理完一批就notifyAll()唤醒生产者
这样既不会把系统累死,又能充分利用资源!
案例2:定时缓存刷新(sleep()版)
某支付系统用sleep()实现每分钟刷新汇率缓存:
new Thread(()->{ while(true) { loadExchangeRate(); // 加载汇率 Thread.sleep(60*1000); // 睡1分钟 } }).start();
简单粗暴但有效,适合这种独立任务~
总结:一句话记住区别 ✨
需要协作通信用wait()(释放锁等通知),单纯延时用sleep()(抱着锁睡大觉)
思考题:这段代码会输出什么?
Object lock = new Object(); new Thread(()->{ synchronized(lock) { lock.wait(1000); System.out.println("A"); } }).start(); Thread.sleep(500); synchronized(lock) { lock.notify(); }
你在项目中踩过wait/sleep的坑吗?欢迎评论区分享经验! 觉得有用记得点赞收藏,下次面试不迷路~
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/188701.html