网站首页 > java教程 正文
从一道面试题看并发编程的"拦路虎"
"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的坑吗?欢迎评论区分享经验! 觉得有用记得点赞收藏,下次面试不迷路~
猜你喜欢
- 2025-09-12 程序员吐槽在阿里混吃等死,每天刷着手机,拿着可怜的30k工资
- 2025-09-12 新人如何自学安卓手机软件开发?_安卓app开发自学教程
- 2025-09-12 我的编程梦----聊聊学习Java_我的编程梦是什么
- 2025-09-12 用Java开发Android App_用Java开发安卓收费吗
- 2025-09-12 Appium + Python + WiFi实现对手机的自动化
- 2025-09-12 轻松实现Lua编程语言在安卓端运行
- 2025-09-12 教大家手机运行linux(以及mc服务器)
- 2025-09-12 不写代码,让 AI 生成手机 APP!保姆级教程
- 2025-09-12 安卓手机编程基础第11篇_安卓手机 编程
- 2025-09-12 详细的手机编程结构讲解,小白都能看的懂,编程一点都不难
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)