线程中的wait()和sleep()有什么区别?
我是否理解wait()-ing线程仍然处于运行模式并使用CPU周期,但sleep()-ing不消耗任何CPU周期正确?
为什么我们同时使用wait()和sleep()?
它们的实现在较低级别上有什么不同?
线程中的wait()和sleep()有什么区别?
我是否理解wait()-ing线程仍然处于运行模式并使用CPU周期,但sleep()-ing不消耗任何CPU周期正确?
为什么我们同时使用wait()和sleep()?
它们的实现在较低级别上有什么不同?
当前回答
这里有很多答案,但我找不到任何一个提到的语义区别。
这与线程本身无关;这两种方法都是必需的,因为它们支持非常不同的用例。
sleep()让线程像以前一样进入睡眠状态,它只是打包上下文并在预定义的时间内停止执行。因此,为了在到期时间之前唤醒它,您需要知道Thread引用。这在多线程环境中并不常见。它主要用于时间同步(例如,在3.5秒内醒来)和/或硬编码的公平性(只睡一会儿,让其他线程工作)。
相反,wait()是一种线程(或消息)同步机制,它允许您通知没有存储引用(也没有关心)的线程。您可以将其视为一个发布-订阅模式(wait == subscribe and notify() == publish)。基本上,使用notify()你是在发送一条消息(甚至可能根本没有收到,通常情况下你并不关心)。
总而言之,通常使用sleep()进行时间同步,使用wait()进行多线程同步。
它们可以在底层操作系统中以同样的方式实现,也可以完全不实现(因为以前版本的Java没有真正的多线程;可能一些小的虚拟机也不这样做)。别忘了Java是在VM上运行的,所以你的代码会根据所运行的VM/OS/HW的不同而转换成不同的东西。
其他回答
方法wait(1000)使当前线程休眠一秒。 如果线程接收到notify()或notifyAll()方法调用,那么线程的睡眠时间可能小于1秒。 调用sleep(1000)会导致当前线程休眠1秒。 此外,睡眠线程不持有锁任何资源。但是等待线程可以。
一个等待线程可以被另一个调用正在被等待的监视器上的notify线程“唤醒”,而一个睡眠线程则不能。另外,一个wait(和notify)必须发生在monitor对象上同步的块中,而sleep则不会:
Object mon = ...;
synchronized (mon) {
mon.wait();
}
此时,当前正在执行的线程等待并释放监视器。另一个线程可以
synchronized (mon) { mon.notify(); }
(在同一个mon对象上)和第一个线程(假设它是在监视器上等待的唯一线程)将被唤醒。
如果有多个线程在监视器上等待,您也可以调用notifyAll—这将唤醒所有线程。但是,只有一个线程能够获取监视器(记住,等待是在同步块中)并继续执行—其他线程将被阻塞,直到它们获得监视器的锁。
另一点是你在对象本身调用wait(即你在对象的监视器上调用wait),而你在线程上调用sleep。
还有一点是,你可以从wait中得到虚假的唤醒(例如,正在等待的线程没有明显的原因就恢复了)。你应该总是等待在某些条件下旋转,如下所示:
synchronized {
while (!condition) { mon.wait(); }
}
简单地说,wait是等待,直到其他线程调用你,而sleep是在指定的一段时间内“不执行下一个语句”。
此外,sleep是Thread类中的静态方法,它在线程上操作,而wait()是Object类中的静态方法,在对象上调用。
还有一点,当你在某个对象上调用wait时,线程同步该对象,然后等待。:)
sleep是Thread的一个方法,wait是Object的一个方法,所以wait/notify是Java中同步共享数据的一种技术(使用monitor),而sleep是线程暂停自身的一种简单方法。
应该从同步块调用:wait()方法总是从同步块调用,即wait()方法需要在调用它的对象之前锁定对象监视器。但是sleep()方法可以从外部同步块调用,即sleep()方法不需要任何对象监视器。
IllegalMonitorStateException:如果wait()方法被调用而没有获得对象锁,则IllegalMonitorStateException在运行时抛出,但sleep()方法从不抛出此类异常。
属于哪个类:wait()方法属于java.lang.Object类,sleep()方法属于java.lang.Thread类。
在对象或线程上调用:wait()方法在对象上调用,而sleep()方法在线程上调用,而不是在对象上。
线程状态:当在对象上调用wait()方法时,持有对象监视器的线程从运行状态变为等待状态,只有在该对象上调用notify()或notifyAll()方法时才能返回到可运行状态。然后线程调度程序将线程从可运行状态调度到运行状态。 当sleep()在线程上被调用时,它会从运行状态转到等待状态,并在休眠时间结束时返回到可运行状态。
从同步块调用时:当wait()方法被调用时,线程离开对象锁。但是sleep()方法在从同步块或方法线程调用时不会留下对象锁。
更多参考资料