在 Java 中,sleep() 和 wait() 都是用于线程控制的方法,但它们在用途、行为以及所属类等方面存在显著的差异。以下是它们之间的主要区别:

  1. 所属类
  • sleep() 是 Thread 类的方法,因此所有线程对象都可以调用它。
  • wait() 是 Object 类的方法,任何对象都可以调用它(因为它是从 Object 类继承的)。但是,它通常在同步代码块或同步方法中调用,因为它依赖于对象的监视器锁。
  1. 释放锁
  • 当线程调用 sleep() 方法时,它并不会释放它持有的锁(如果有的话)。这意味着如果其他线程试图访问由该线程持有的锁,它们将会被阻塞,直到 sleep() 方法结束并且该线程重新获得执行权。
  • 当线程调用 wait() 方法时,它会释放它持有的对象监视器锁,允许其他线程进入同步代码块或方法。当其他线程调用 notify() 或 notifyAll() 方法时,等待的线程将被唤醒并重新尝试获取锁。
  1. 异常
  • sleep() 方法会抛出 InterruptedException,如果线程在等待时被中断,它会清除中断状态并抛出此异常。
  • wait() 方法也会抛出 InterruptedException,但处理方式与 sleep() 不同。如果线程在等待时被中断,它会清除中断状态并立即返回,而不是抛出异常。这允许程序员在捕获中断后决定如何处理它。
  1. 用途
  • sleep() 通常用于使线程暂停一段时间,以便其他线程可以执行。它并不依赖于对象的监视器锁。
  • wait() 和 notify()/notifyAll() 通常一起使用,以实现线程之间的通信和协作。它们依赖于对象的监视器锁,并允许一个线程等待另一个线程完成某个任务或满足某个条件。
  1. 唤醒方式
  • sleep() 会在指定的时间后自动唤醒线程。
  • wait() 需要其他线程调用同一个对象的 notify() 或 notifyAll() 方法来唤醒。
  1. 超时
  • sleep() 方法有一个重载版本,允许指定一个超时时间(以毫秒为单位)。如果线程在等待期间超时,它将自动唤醒。
  • wait() 方法也有一个重载版本,允许指定一个超时时间。如果线程在等待期间超时或收到 notify()/notifyAll() 调用,它将唤醒。
  1. 状态
  • 调用 sleep() 的线程处于 TIMED_WAITING 状态。
  • 调用 wait() 的线程处于 WAITING 或 TIMED_WAITING 状态(取决于是否指定了超时时间)。