线程中的wait()和sleep()有什么区别?
我是否理解wait()-ing线程仍然处于运行模式并使用CPU周期,但sleep()-ing不消耗任何CPU周期正确?
为什么我们同时使用wait()和sleep()?
它们的实现在较低级别上有什么不同?
线程中的wait()和sleep()有什么区别?
我是否理解wait()-ing线程仍然处于运行模式并使用CPU周期,但sleep()-ing不消耗任何CPU周期正确?
为什么我们同时使用wait()和sleep()?
它们的实现在较低级别上有什么不同?
当前回答
在研究了wait和sleep之后,我总结了一些不同的关键注意事项,首先看一下使用wait()和sleep()的示例:
例1:使用wait()和sleep():
synchronized(HandObject) {
while(isHandFree() == false) {
/* Hand is still busy on happy coding or something else, please wait */
HandObject.wait();
}
}
/* Get lock ^^, It is my turn, take a cup beer now */
while (beerIsAvailable() == false) {
/* Beer is still coming, not available, Hand still hold glass to get beer,
don't release hand to perform other task */
Thread.sleep(5000);
}
/* Enjoy my beer now ^^ */
drinkBeers();
/* I have drink enough, now hand can continue with other task: continue coding */
setHandFreeState(true);
synchronized(HandObject) {
HandObject.notifyAll();
}
让我们明确一些关键的注意事项:
呼吁: wait():调用当前持有handdobject对象的线程 sleep():在线程上调用执行任务获取啤酒(是类方法,因此影响当前运行的线程) 同步: wait():当同步多线程访问同一对象(HandObject)时(当多个线程之间需要通信时(线程执行编码,线程执行获取啤酒)访问同一对象(HandObject) sleep():当等待状态继续执行时(等待啤酒可用) 持有锁: wait():释放锁,让其他对象有机会执行(HandObject是空闲的,你可以做其他工作) sleep():保持锁至少t次(或直到中断)(我的工作仍然没有完成,我继续持有锁,等待一些条件继续) 唤醒条件: wait():直到调用notify(), notifyAll()从对象 Sleep():直到至少超时或调用中断 最后一点是当estani表示:
通常使用sleep()进行时间同步,使用wait()进行时间同步 multi-thread-synchronization。
如果我说错了,请指正。
其他回答
实际上,所有这些都在Java文档中有清楚的描述(但我是在阅读答案后才意识到这一点)。
http://docs.oracle.com/javase/8/docs/api/index.html:
wait() -当前线程必须拥有该对象的监视器。线程释放 该监视器的所有权,并等待直到另一个线程通知 在此对象的监视器上等待的线程可以通过 调用notify方法或notifyAll方法。那么线程 等待,直到它可以重新获得监视器的所有权并恢复执行。
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()方法在从同步块或方法线程调用时不会留下对象锁。
更多参考资料
wait()必须被synchronized包围,当线程进入synchronized块或方法时,它意味着获得锁,所以它不阻塞,调用wait意味着释放锁,所以它退出synchronized然后阻塞,thread .sleep()导致当前线程在指定的时间内暂停执行。线程不会失去任何监视器的所有权
我发现这篇文章很有帮助。它将Thread.sleep(), Thread.yield()和Object.wait()之间的区别放在人类术语中。引用:
这一切最终都会传到操作系统的调度程序 将时间片分发给进程和线程。 sleep(n)表示“我已经用完了我的时间片,请不要给我 再来一次,至少n毫秒。”操作系统甚至不会尝试这样做 调度睡眠线程,直到请求的时间过去。 yield()表示“我已经完成了我的时间片,但我仍然有工作要做 做的。”操作系统可以立即给线程另一个时间片, 或者给CPU的其他线程或进程生成线程 就这么放弃了。 wait()表示“我完成了我的时间片。别再给我了 时间片,直到有人调用notify()。”与sleep()一样,操作系统不会这样做 甚至尝试调度您的任务,除非有人调用notify()(或其中之一) 还有其他一些醒来的场景)。 线程在执行时也会丢失剩余的时间片 阻塞IO和其他一些情况下。如果线程工作 在整个时间片中,操作系统强制控制大致为 如果已经调用yield(),则其他进程可以运行。 你很少需要yield(),但是如果你有一个计算量很大的应用程序 逻辑任务边界,插入yield()可以改善系统 响应性(以时间为代价——上下文切换,甚至只是 到操作系统并返回,不是免费的)。衡量和测试你的目标 在乎,一如既往。
方法wait(1000)使当前线程休眠一秒。 如果线程接收到notify()或notifyAll()方法调用,那么线程的睡眠时间可能小于1秒。 调用sleep(1000)会导致当前线程休眠1秒。 此外,睡眠线程不持有锁任何资源。但是等待线程可以。