使用Object.wait(millisec)来模拟睡眠

这是我在一些我正在维护的代码中看到的代码片段。

Object lock = new Object(); synchronized( lock ) { try { lock.wait( 50000 ); Thread.sleep( 3000 ); } catch(Exception ex) { } } 

开发人员希望暂停当前线程一段时间,并使用Object#wait作为机制。 显然,由于这个原因,使用wait / notify协议是不好的forms; 但是,调用wait(millisec)和Thread.sleep之间有什么重大区别吗?

除了必须在等待之前获得一个监视器()之外,只要没有外部人员可以进行.notify(),就不会有任何重大差异。

在古代Java代码中,您会看到人们使用wait()而不是Thread.sleep(),因为Thread.sleep()会在没有抢占式多任务处理的情况下冻结整个应用程序(我正在看你OS9)。 技术上等待()也让你使用纳米分辨率等待,但实际上它们很少准确。

请注意, 同步块中使用Object.wait()和Thread.sleep()有一个关键区别:Thread.sleep()不会释放锁定的监视器,因此没有其他人可以成为监视器的所有者。

此外,Object.wait()不保证严格遵守指示的延迟。 首先,在延迟过去之后,线程可能仍在等待同时成为监视所有者的另一个线程; 它可能会与等待抢占显示器的其他线程竞争。

第二,神秘的虚假唤醒,正如Java 6 API javadoc中所描述的那样:

线程也可以在没有被通知,中断或超时的情况下唤醒,即所谓的虚假唤醒。

不太可能,使用Object.wait()的每一段代码都应该考虑它。

你说使用wait / notify这是“显然”不好的forms,但我没有看到它有什么问题。 不可否认,跟着sleep呼叫是非常奇怪的(并且吞咽exception是坏的),但我现在肯定使用Object.wait作为“可破坏的睡眠”。

想象一下,你每分钟都有一个线程轮询资源,但是如果发生了某些事情你想要被唤醒(例如资源位置已经改变,或者计时器频率已经改变,或者程序想要以优雅的方式退出)。 使用wait/notify非常有效 – 它肯定比从其他地方调用线程上的interrupt更干净,因为在你实际处理而不是等待时发生通知并不重要。