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

时间:2009-04-02 04:45:25

标签: java multithreading concurrency

以下是我在维护的一些代码中看到的一段代码。

Object lock = new Object();

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

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

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:4)

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

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

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

  

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

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

答案 2 :(得分:3)

你说使用wait / notify这是“显然”不好的形式,但我没有看到它有任何问题。无可否认地跟进sleep电话是非常奇怪的(吞咽异常很糟糕),但我现在肯定使用Object.wait作为“可破坏的睡眠”。

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