线程中的wait()和sleep()有什么区别?

我是否理解wait()-ing线程仍然处于运行模式并使用CPU周期,但sleep()-ing不消耗任何CPU周期正确?

为什么我们同时使用wait()和sleep()?

它们的实现在较低级别上有什么不同?


当前回答

从oracle文档页面的wait()方法的对象:

public final void wait()

导致当前线程等待,直到另一个线程调用该对象的notify()方法或notifyAll()方法。换句话说,这个方法的行为就像简单地执行调用wait(0)一样。 当前线程必须拥有该对象的监视器。线程释放该监视器的所有权并等待,直到另一个线程通知等待该对象监视器的线程被唤醒 可能会出现中断和虚假唤醒 此方法只能由该对象的监视器的所有者的线程调用

这个方法抛出

IllegalMonitorStateException -如果当前线程不是对象的监视器的所有者。 InterruptedException——如果任何线程在当前线程等待通知之前或期间中断了当前线程。抛出此异常时,当前线程的中断状态将被清除。

从oracle文档页关于Thread类的sleep()方法:

public static void sleep(long millis)

使当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,这取决于系统计时器和调度器的精度和准确性。 线程不会失去任何监视器的所有权。

这个方法抛出:

IllegalArgumentException -如果millis的值为负 InterruptedException -如果任何线程中断了当前线程。抛出此异常时,当前线程的中断状态将被清除。

其他关键区别:

Wait()是一个非静态方法(实例方法),不同于静态方法sleep()(类方法)。

其他回答

方法wait(1000)使当前线程休眠一秒。 如果线程接收到notify()或notifyAll()方法调用,那么线程的睡眠时间可能小于1秒。 调用sleep(1000)会导致当前线程休眠1秒。 此外,睡眠线程不持有锁任何资源。但是等待线程可以。

Sleep()方法导致当前线程在指定的时间内从运行状态转移到阻塞状态。如果当前线程拥有任何对象的锁,那么它会一直持有它,这意味着其他线程不能在该类对象中执行任何同步方法。

Wait()方法会导致当前线程在指定的时间内进入阻塞状态或直到notify,但在这种情况下,线程会释放对象的锁(这意味着其他线程可以执行调用对象的任何同步方法)。

在这里,我列出了wait()和sleep()方法之间的一些重要区别。 PS:也可以点击链接查看库代码(内部工作,只是为了更好地理解而玩一下)。

wait ()

Wait()方法释放锁。 wait()是Object类的方法。 wait()是非静态方法——public final void wait()会抛出InterruptedException{//…} wait()应该由notify()或notifyAll()方法通知。 Wait()方法需要从循环中调用,以处理假警报。 wait()方法必须从同步上下文(即同步方法或块)调用,否则将抛出IllegalMonitorStateException

睡眠()

Sleep()方法不释放锁。 sleep()是java.lang.Thread类的方法。 sleep()是静态方法——public static void sleep(long millis, int nanos)会抛出InterruptedException{//…} 在指定的时间量之后,sleep()将完成。 Sleep()最好不要从循环中调用(即。参见下面的代码)。 Sleep()可以从任何地方调用。没有具体的要求。

参考:等待和睡眠的区别

调用等待和睡眠方法的代码片段

synchronized(monitor){
    while(condition == true){ 
        monitor.wait()  //releases monitor lock
    }

    Thread.sleep(100); //puts current thread on Sleep    
}

在我看来,这两种机制之间的主要区别在于,睡眠/中断是处理线程的最基本方式,而等待/通知是一种抽象,旨在使线程间的通信更容易。这意味着睡眠/中断可以做任何事情,但这个特定的任务更难完成。

为什么等待/通知更合适?以下是一些个人考虑:

它加强了中央集权。它允许使用单个共享对象协调一组线程之间的通信。这大大简化了工作。 它强制同步。因为它使程序员将等待/通知调用包装在同步块中。 它与线程的起源和编号无关。使用这种方法,您可以任意添加更多线程,而无需编辑其他线程或跟踪现有线程。如果使用sleep/interrupt,首先需要保留对休眠线程的引用,然后手动逐个中断它们。

一个来自现实生活的例子很好地解释了这一点,一个经典的餐厅和员工之间用来沟通的方法:服务员把顾客的要求放在一个中心的地方(一块软木板,一张桌子等),摇铃,然后厨房的工人来接受这些要求。一旦有菜准备好了,厨房工作人员就会再次按铃,让服务员知道并把菜送到顾客面前。

等待和睡眠的方法非常不同:

睡眠无法“唤醒”, 而wait在等待期间有一种“唤醒”的方式,由另一个线程调用notify或notifyAll。

仔细想想,这些名字在这方面令人困惑;然而,sleep是一个标准名称,而wait就像Win API中的WaitForSingleObject或WaitForMultipleObjects。