Java并发编程必知:wait()与sleep()的6大核心区别及实战避坑指南

Java并发编程必知:wait()与sleep()的6大核心区别及实战避坑指南从一道面试题看并发编程的 拦路虎 Wait 和 Sleep 有什么区别 这道题是不是让你挠头 就像餐厅等位时 有人占着座位玩手机 sleep 有人把座位让给别人去候客区等叫号 wait

大家好,欢迎来到IT知识分享网。

从一道面试题看并发编程的”拦路虎”

“Wait 和 Sleep 有什么区别?”这道题是不是让你挠头? 就像餐厅等位时,有人占着座位玩手机(sleep()),有人把座位让给别人去候客区等叫号(wait())——看似都是”等”,但背后的逻辑天差地别!今天咱们用3个真实案例+2张对比表,把这对”孪生兄弟”彻底讲明白,让你面试再也不慌!

核心区别对比:6大维度吃透底层差异

一张表看懂核心差异 ⚠️

Java并发编程必知:wait()与sleep()的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. 线程状态变化

Java并发编程必知:wait()与sleep()的6大核心区别及实战避坑指南

  • wait():进入WAITING状态,被唤醒后要重新抢锁
  • sleep():进入TIMED_WAITING状态,醒了直接继续跑

使用场景深度解析:该用哪个?怎么选?

场景1:生产者-消费者模型(必须用wait()!)

比如电商订单系统,生产者(下单线程)和消费者(处理线程)要协作:

  • 库存满了?生产者wait()释放锁,等消费者处理完再notify()唤醒
  • 库存空了?消费者wait(),等生产者补货到了再唤醒
Java并发编程必知:wait()与sleep()的6大核心区别及实战避坑指南

核心代码就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

(0)
上一篇 2025-09-23 12:10
下一篇 2025-09-23 12:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信