面试题:Java 中 Thread.sleep 和 Thread.yield 的区别?

Thread.sleep() 和 Thread.yield() 都是用于控制线程执行的静态方法,但它们的目的和行为有着明显的区别:

Thread.sleep(long millis)

  • 目的:使当前正在执行的线程暂停执行指定的时间(以毫秒为单位),在此期间,该线程不会占用CPU资源。这通常用于延迟操作或是在轮询场景中让出CPU。
  • 参数:接受一个长整型参数,表示需要暂停的毫秒数。也可以接受第二个参数,表示纳秒数,即 Thread.sleep(long millis, int nanos)
  • 作用:调用 Thread.sleep() 会导致当前线程进入阻塞状态,直到经过了指定的时间后才重新进入可运行状态,等待调度器再次分配时间片给它。
  • 异常处理:可能会抛出 InterruptedException 异常,因此需要进行异常处理。
try {
    Thread.sleep(1000); // 让当前线程暂停1秒钟
} catch (InterruptedException e) {
    e.printStackTrace();
}

Thread.yield()

  • 目的:建议Java虚拟机的线程调度器重新评估线程的优先级,并允许其他处于就绪状态的线程有机会运行。这是一种提示而非强制命令,因为是否真正让出CPU取决于底层的操作系统及其线程调度算法。
  • 参数:无参数。
  • 作用:调用 Thread.yield() 并不会导致线程进入阻塞状态,而是直接回到可运行状态,这意味着它仍然可能在下一次循环中被调度器选中继续执行。
  • 异常处理:不抛出任何异常。
Thread.yield(); // 建议调度器让出当前线程的执行权

主要区别

  1. 状态转换
    • Thread.sleep() 会使线程从运行状态转入阻塞状态,直到设定的时间结束后才会重新变为可运行状态
    • Thread.yield() 则只是建议调度器将当前线程转回可运行状态,并不保证会立即停止当前线程的执行,也不影响其后续是否会被调度执行。
  2. 确定性
    • 使用 Thread.sleep() 可以确切地知道线程会被暂停多长时间。
    • 而 Thread.yield() 的效果依赖于线程调度器的实现,不能保证一定会让出CPU,也不能预测何时该线程会被再次调度执行。
  3. 应用场景
    • Thread.sleep() 更适合用于定时任务、简单的延时逻辑等场景。
    • Thread.yield() 适用于希望减少某个线程对CPU的独占,试图提高并发度的情况下,但实际使用较少,因为它提供的是一种非确定性的行为,且其效果难以预测。

理解这些差异有助于正确选择合适的方法来控制线程的行为。例如,在编写高并发程序时,如果需要精确控制线程的执行间隔,则应使用 Thread.sleep();而在尝试优化多线程程序的性能时,可以考虑使用 Thread.yield(),尽管它的效果可能不如预期的那样明显。

THE END
喜欢就支持一下吧
点赞13 分享