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