Thread.sleep 会立即响应中断并抛出 InterruptedException,不释放 synchronized 锁或 Lock;sleep(0) 仅触发调度器重评估,不保证线程切换;捕获异常后必须恢复中断状态,否则中断信号丢失。

Thread.sleep 会响应中断吗?
会,而且是立即响应。调用 Thread.sleep 期间如果线程被中断,它不会等睡完才抛异常,而是马上退出并抛出 InterruptedException。
这是它和 Object.wait 的关键区别之一:sleep 不释放锁,但中断信号能穿透进去。
- 必须在 try-catch 中处理
InterruptedException,否则编译不通过 - 捕获后别直接吞掉异常——至少要恢复中断状态:
Thread.currentThread().interrupt() - 如果上层逻辑依赖中断来终止任务(比如 ExecutorService 的 shutdownNow),忽略它会导致线程无法及时退出
Thread.sleep 会不会释放 synchronized 锁?
不会。这是最容易混淆的点:Thread.sleep 只让出 CPU,不释放任何锁。
也就是说,哪怕你在 synchronized 块里调用了 sleep,其他线程依然拿不到这把锁,直到 sleep 结束或当前线程退出同步块。
立即学习“Java免费学习笔记(深入)”;
- 想“挂起并释放锁”,得用
Object.wait(),而不是sleep - 误用
sleep替代wait是死锁常见诱因——尤其在等待某个条件成立时 - Lock 接口下的
lock.lock()同样不受sleep影响,锁依然持有
为什么 sleep(0) 有时被用来让出 CPU?
Thread.sleep(0) 是 JVM 提供的一种“礼貌性让出”机制:它不指定休眠时间,但会触发线程调度器重新评估优先级,可能把当前线程暂时切走,给同优先级线程执行机会。
但它不是 yield 的替代品,也不保证切换发生,更不释放锁。
- 比
Thread.yield()更可靠一点(某些 JVM 实现中 yield 可能被忽略) - 仍处于当前线程的同步块内,锁照常持有
- 不要指望靠它实现精确协作;高并发场景下它基本不可靠,仅适合低争用、调试或粗粒度让权
中断被忽略后线程真的“醒不来”了吗?
不是醒不来,而是中断状态被清除了。一旦 InterruptedException 被抛出,JVM 会自动清除当前线程的中断标志位。
如果你没手动恢复,后续调用 Thread.interrupted() 就会返回 false,isInterrupted() 也查不到痕迹——等于中断“丢失”了。
- 正确做法是在 catch 块末尾加一句:
Thread.currentThread().interrupt() - 如果 sleep 在循环里,每次捕获异常后都该恢复中断,否则外层循环可能永远检测不到中断
- 很多开源库(如 Apache Commons、Guava)的阻塞工具类内部都做了这个恢复动作,自己写别漏掉
interrupt() 调用,就可能让整个任务取消逻辑失效。










