wait()立即释放锁,sleep()不释放锁;wait()需在synchronized中调用且依赖notify协作唤醒,sleep()是独立计时暂停;前者属并发通信原语,后者属调度层控制指令。

锁释放机制:根本差异决定行为边界
wait() 会立即释放当前线程持有的对象锁,其他线程可立刻竞争并进入 synchronized 块;sleep() 完全不碰锁——哪怕线程正抱着锁睡觉,别的线程也只能干等。
这个区别直接导致两类典型错误:
- 在非同步上下文中调用 wait() → 抛 IllegalMonitorStateException
- 用 sleep() 替代 wait() 等待共享条件(如队列非空)→ 其他线程无法通过 notify() 提前唤醒,只能硬等超时,既浪费 CPU 又延迟响应
唤醒逻辑:协作式等待 vs 时间驱动暂停
wait() 是纯协作模型:它不关心时间,只等别人喊。必须配合同一对象上的 notify() 或 notifyAll() 才能退出等待;即使设了超时(wait(long)),本质仍是“条件未满足时防死等”,不是定时任务。
sleep() 则是单向计时器:传入毫秒数,时间一到自动恢复运行,无需任何外部干预。中断时抛 InterruptedException,且不修改中断状态,处理更直接。
关键细节:
- wait() 被中断时,会先清除线程中断标志,再抛异常 → 若忽略该异常,后续逻辑可能永远收不到中断信号
- 正确做法是在 catch 块中手动重置:Thread.currentThread().interrupt()
- sleep() 中断后异常即终止休眠,无需额外补操作
CPU 与系统资源调度表现
两者都让出 CPU 执行权,但资源让渡深度不同:
- sleep():线程进入 TIMED_WAITING 状态,OS 认为它“仍在工作”,不释放锁也不出让执行资源权限,仅暂停执行
- wait():线程进入 WAITING 状态,进入对象的等待队列,彻底让出锁 + 让出 CPU + 出让同步控制权,OS 可调度其他线程使用该对象的临界区
这也解释了为什么 sleep(0) 有特殊用途:它不暂停,但强制触发一次 CPU 重新调度,常用于让权争抢;而 wait() 没有零时长版本——它天生就不是为“微调调度”设计的。
方法归属与调用约束体现设计意图
sleep() 是 Thread 类的静态方法,面向“线程自身行为控制”,调用无门槛,适合做延时、心跳、节流等独立操作。
wait() 是 Object 类的实例方法,绑定具体对象监视器(monitor),天然携带通信语义。必须在 synchronized 块内调用,因为只有持锁者才有资格“释放锁并等待”——这是 Java 并发模型中“等待-通知”范式的基石。
简单说:sleep() 是线程在调度层的暂停指令;wait() 是线程在并发协作层的通信原语。它们不在同一抽象层级,混用等于错配语义。

















