wait会释放锁而sleep不会——wait必须在synchronized中调用,释放锁后进入等待队列,需被notify或中断唤醒并重新竞争锁;sleep是thread静态方法,保持所有已持锁,仅暂停线程指定时间。

wait 会释放锁,sleep 不会释放锁——这是最核心的区别。两者虽然都能让线程暂停执行,但对同步资源(即 monitor 锁)的处理方式完全不同,直接影响并发行为和是否可能引发死锁。
wait 必须在 synchronized 块中调用,且会主动释放锁
调用 wait() 前,线程必须已经持有该对象的 monitor 锁(即处于 synchronized 方法或代码块内)。一旦执行 wait,线程立刻释放该锁,并进入对象的等待队列(wait set),直到被 notify() 或 notifyAll() 唤醒,或超时返回。唤醒后需重新竞争锁,获得锁后才能继续执行。
- 不满足 synchronized 上下文时调用 wait,会抛出
IllegalMonitorStateException - wait 是 Object 类方法,作用于调用它的那个对象实例
- 典型场景:生产者-消费者模型中,消费者发现缓冲区为空,调用
buffer.wait()释放 buffer 锁,让生产者有机会加锁并写入
sleep 是 Thread 的静态方法,与锁无关
Thread.sleep(long) 只是让当前线程暂停指定毫秒数,期间它**继续保持已持有的所有锁**。其他线程无法获取这些锁,哪怕只是想读共享状态也可能被阻塞。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 可在任何地方调用,无需同步上下文
- 睡眠结束后线程直接恢复运行(进入就绪态),不涉及锁竞争或唤醒机制
- 常见误用:在 synchronized 块里 sleep 替代 wait,导致本该让出锁的时机没让,造成其他线程长时间饥饿
唤醒机制与中断响应也不同
wait 支持被 notify 唤醒,也响应中断(抛出 InterruptedException);sleep 同样响应中断,但不会被 notify 唤醒——它只认时间或中断。
- wait() / wait(timeout) 都可能因虚假唤醒(spurious wakeup)提前返回,所以必须配合 while 循环检查条件
- sleep 不会虚假唤醒,但若被中断,仍需捕获异常并决定是否退出或重试
- 二者都清空中断状态(调用后
Thread.interrupted()返回 true,且内部标志位被清除)
简单对比表
| 行为 | wait() | sleep() |
|------|--------|---------|
| 是否释放锁 | ✅ 是(释放当前对象锁) | ❌ 否(保持所有已持锁) |
| 调用位置限制 | 必须在 synchronized 中 | 任意位置 |
| 所属类 | Object | Thread |
| 唤醒方式 | notify/notifyAll/中断/超时 | 时间到期/中断 |
| 是否需要循环检查条件 | ✅ 强烈建议(防虚假唤醒) | ❌ 通常不需要 |
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










