协慌网

登录 贡献 社区

wait()和 sleep()之间的区别

Threads 中wait()sleep()有什么区别?

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

为什么我们 wait()sleep()如何实现他们在一个较低的水平有什么不同?

答案

wait可以被另一个线程 “唤醒”,该线程在正在等待的监视器上调用notifysleep不能。此外, wait (和notify )必须在监视器对象上synchronized的块中发生,而sleep不会:

Object mon = ...;
synchronized (mon) {
    mon.wait();
}

此时,当前正在执行的线程等待并释放监视器 。另一个线程可能会

synchronized (mon) { mon.notify(); }

(在同一个mon对象上)和第一个线程(假设它是在监视器上等待的唯一线程)将被唤醒。

如果监视器上有多个线程正在等待,您也可以调用notifyAll - 这将唤醒所有线程。但是,只有一个线程能够抓住监视器(记住waitsynchronized块中)并继续 - 其他线程将被阻塞,直到它们可以获取监视器的锁定。

另一点是你在Object本身上调用wait (即你在对象的监视器上等待),而你在Thread上调用sleep

还有一点是你可以从wait获得虚假的唤醒(即正在等待恢复的线程没有明显的原因)。你应该总是wait ,而在某些条件下纺如下:

synchronized {
    while (!condition) { mon.wait(); }
}

没有提到的一个关键区别是在睡眠时线程不会释放其持有的锁,而等待释放该对象的锁wait()被调用的。

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}

我觉得这篇文章很有帮助。它将Thread.sleep()Thread.yield()Object.wait()之间的区别用于人类术语。报价:

这一切最终都归结为操作系统的调度程序,它将时间片分配给进程和线程。

sleep(n)“我已完成了我的时间片,请不要给我另一个至少 n 毫秒。”操作系统甚至没有尝试安排睡眠线程,直到请求的时间过去。

yield()“我已经完成了我的时间片,但我还有工作要做。”操作系统可以自由地立即给线程另一个时间片,或者给一些其他线程或处理 CPU,让步线程放弃了。

wait()说: “我已完成了我的时间片。在有人调用 notify()之前不要给我另一个时间片。“sleep() ,操作系统甚至不会尝试安排你的任务,除非有人调用notify() (或者发生其他一些其他唤醒场景)。

线程在执行阻塞 IO 时以及在其他一些情况下也会丢失剩余的时间片。如果一个线程在整个时间片中工作,那么操作系统会强制控制,就像调用yield()一样,以便其他进程可以运行。

你很少需要yield() ,但是如果你有一个具有逻辑任务边界的计算量大的应用程序,插入yield() 可能会提高系统响应能力(以时间为代价 - 上下文切换,甚至只是操作系统和后退,不是 ' 免费)。一如既往地衡量和测试您关心的目标。