thread.sleep 是真挂起,使线程进入 timed_waiting 状态、释放 cpu 且可被中断;thread.yield 是假让座,仅提示调度器礼让,线程保持 runnable 状态、不保证切换、现代场景基本弃用。

要区分 Thread.sleep 和 Thread.yield 在 CPU 调度中的让步行为,关键不是看“谁更谦让”,而是看“让得有多真”——一个真睡,一个假让。
Thread.sleep:真挂起,带时限的CPU退出
调用 Thread.sleep(ms) 后,线程立刻进入 TIMED_WAITING 状态,操作系统不再把它放进调度队列,CPU 时间片彻底交出。它不执行、不争资源、不响应普通调度,只等时间到或被中断唤醒。
- 必须传毫秒(或毫秒+纳秒),时间一到自动回到 RUNNABLE 状态
- 不释放锁——哪怕在 synchronized 块里 sleep,锁还牢牢攥着
- 会抛
InterruptedException,必须 try-catch 或 throws,否则编译不过 - 适合场景:轮询间隔(如每 500ms 查一次状态)、限流降频、模拟耗时、避免空转
Thread.yield:假让座,纯提示型CPU礼让
Thread.yield() 不改变线程状态,仍保持在 RUNNABLE,只是向 JVM 调度器发个软信号:“我愿意歇会儿”。调度器可以当没听见,下一刻就又把它挑回来运行。
- 无参数、无异常、不设时长,调完马上可能继续执行
- 同样不释放锁,和 sleep 一样,持有锁不变
- 只对同优先级线程“礼貌有效”,高优先级线程压根不受影响
- 现代 JVM(尤其 HotSpot + Linux)中常被忽略,实际效果趋近于无
两者都不释放锁,但让出方式天差地别
这是最容易混淆的一点:sleep 和 yield 都不释放锁,但它们让出 CPU 的机制完全不同。
-
sleep是“人走了,门还锁着”——线程阻塞,锁照持,别人想进只能干等 -
yield是“人起身让座,但手还搭在扶手上”——线程仍在就绪队列里候着,随时可能抢回座位 - 若你本意是“让别人趁机拿到锁”,那两个方法都做不到;真正释放锁只能靠退出 synchronized 块或显式 unlock
怎么选?看你要的是“暂停”还是“打个招呼”
一句话判断:需要确定停多久 → 用 sleep;只想试试看能不能让一下 → yield 基本可删。
- 写限速逻辑、防忙等、加延时重试 → 必用
sleep(1)或sleep(10),别用 yield 拼循环 - 调试线程调度行为、嵌入式环境微调、或老代码兼容 → 才考虑 yield
- 在 GUI 线程或长时间计算中怕卡界面?
sleep(0)比 yield 更可靠(触发完整调度重评估) - 面试被问 yield,重点答:它是建议而非保证,现代场景已基本弃用











