thread.sleep()让当前线程休眠指定毫秒数且不释放锁,必须处理interruptedexception;timeunit.sleep()语义更清晰但底层仍调用它;忽略中断或错误处理会导致协作失效,休眠精度受系统限制。

Java里让线程休眠,Thread.sleep() 是最直接的方式
它会让当前线程暂停执行指定毫秒数,期间不释放锁(这点很重要),且必须处理 InterruptedException。常见错误是忽略异常处理,或在循环中没重置中断状态。
使用时注意:
-
Thread.sleep(1000)休眠 1 秒,参数单位固定为毫秒,容易写错成秒或微秒 - 若线程被其他线程调用
interrupt(),会立即抛出InterruptedException,并清除中断标志 - 休眠中不会释放已持有的
synchronized锁,这点和Object.wait()不同 - 不能在静态上下文或非线程执行流中调用(比如没在
run()里)
TimeUnit 不是替代 Thread.sleep(),而是让时间单位更可读
TimeUnit 是工具类,它的 sleep() 方法底层仍调用 Thread.sleep(),只是把单位转换封装了。例如 TimeUnit.SECONDS.sleep(2) 等价于 Thread.sleep(2000),但语义更清晰。
优势场景:
立即学习“Java免费学习笔记(深入)”;
- 需要按秒、分钟、小时等自然单位控制休眠时,避免手算毫秒(比如
TimeUnit.MINUTES.sleep(5)比Thread.sleep(5 * 60 * 1000)更安全) - 配合
BlockingQueue、ScheduledExecutorService等 API 使用时,它们大量接受TimeUnit参数,保持风格统一 - 单位转换逻辑由 JDK 保证,不会因整型溢出或计算顺序出错(比如
60 * 60 * 1000 * 24在 int 范围内安全,但写错顺序可能先溢出)
别在 catch (InterruptedException) 里简单吞掉异常
这是高频陷阱。很多代码写成:
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// 忽略或只打日志
}这会导致上层无法感知线程已被中断,后续的中断响应逻辑(如优雅退出)全部失效。正确做法是:
- 恢复中断状态:
Thread.currentThread().interrupt(); - 或根据业务决定是否向上抛出(比如在
Runnable中无法 throws,就恢复后继续运行或退出) - 不要用
e.printStackTrace()代替处理逻辑
休眠精度受系统调度影响,别指望精确到毫秒
Thread.sleep(1) 可能实际停 10ms 甚至更久,尤其在 Windows 上默认调度周期约 15ms。Linux 下可通过 timer_create() 提升精度,但 JVM 不暴露该控制。
所以:
- 别用
sleep()做高精度定时(用ScheduledExecutorService或System.nanoTime()自旋校准) - 短于 10ms 的休眠基本无意义,还增加上下文切换开销
- 如果需要“至少休眠 X 时间”,
sleep()满足;如果要求“严格等于 X 时间”,它做不到
真正复杂的地方不在怎么写,而在中断状态管理和休眠意图的传达——前者影响线程协作可靠性,后者决定代码是否可维护。










