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

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

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

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


当前回答

让我们假设你正在听到歌曲。

只要当前歌曲正在运行,下一首歌就不会播放,即由下一首歌调用Sleep()

如果你完成了这首歌,它会停止,直到你选择播放按钮(notify())它才会播放,即由当前歌曲调用的wait()。

在这两种情况下,歌曲都进入等待状态。

其他回答

睡眠/中断和等待/通知之间的一个潜在的巨大区别是

在sleep()期间调用interrupt()总是抛出异常(例如InterruptedException),而 在wait()期间调用notify()不会。

在不需要的时候生成异常是低效的。如果线程之间的通信速率很高,那么如果一直调用interrupt,就会产生很多异常,这完全是浪费CPU。

等待会释放锁,而睡眠不会。处于等待状态的线程可以在调用notify或notifyAll时被唤醒。但是在睡眠的情况下,线程保持锁,并且只有在睡眠时间结束时才有资格。

从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()(类方法)。

实际上,所有这些都在Java文档中有清楚的描述(但我是在阅读答案后才意识到这一点)。

http://docs.oracle.com/javase/8/docs/api/index.html:

wait() -当前线程必须拥有该对象的监视器。线程释放 该监视器的所有权,并等待直到另一个线程通知 在此对象的监视器上等待的线程可以通过 调用notify方法或notifyAll方法。那么线程 等待,直到它可以重新获得监视器的所有权并恢复执行。

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

这些方法用于不同的事情。

Thread.sleep(5000);   // Wait until the time has passed.

Object.wait();        // Wait until some other thread tells me to wake up.

Thread.sleep(n)可以被中断,但是Object.wait()必须被通知。 可以指定等待的最大时间:Object.wait(5000),这样就可以使用wait,呃,睡眠,但这样你就不得不使用锁了。

这两种方法都不会在休眠/等待时使用cpu。

这些方法是使用本地代码实现的,使用类似的结构,但方式不同。

自己寻找:本机方法的源代码是否可用?文件/src/share/vm/prims/jvm.cpp是起点…