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(); // 建议调度器让出当前线程的执行权
主要区别
- 状态转换:
Thread.sleep()
会使线程从运行状态转入阻塞状态,直到设定的时间结束后才会重新变为可运行状态。Thread.yield()
则只是建议调度器将当前线程转回可运行状态,并不保证会立即停止当前线程的执行,也不影响其后续是否会被调度执行。
- 确定性:
- 使用
Thread.sleep()
可以确切地知道线程会被暂停多长时间。 - 而
Thread.yield()
的效果依赖于线程调度器的实现,不能保证一定会让出CPU,也不能预测何时该线程会被再次调度执行。
- 使用
- 应用场景:
Thread.sleep()
更适合用于定时任务、简单的延时逻辑等场景。Thread.yield()
适用于希望减少某个线程对CPU的独占,试图提高并发度的情况下,但实际使用较少,因为它提供的是一种非确定性的行为,且其效果难以预测。
理解这些差异有助于正确选择合适的方法来控制线程的行为。例如,在编写高并发程序时,如果需要精确控制线程的执行间隔,则应使用 Thread.sleep()
;而在尝试优化多线程程序的性能时,可以考虑使用 Thread.yield()
,尽管它的效果可能不如预期的那样明显。
THE END