【问题标题】:Using Object.wait(millisec) to simulate sleep使用 Object.wait(millisec) 模拟睡眠
【发布时间】:2009-04-02 04:45:25
【问题描述】:

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

Object lock = new Object();

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

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

【问题讨论】:

    标签: java multithreading concurrency


    【解决方案1】:

    除了必须在 wait() 之前获得一个监视器之外,只要没有外部人员会 .notify() ing,就没有什么大的区别了。

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

    【讨论】:

    • 好的,我想暂停一个线程 x 秒。我如何决定我应该使用 wait() 还是 sleep() ?
    • 我在回答中解释了这一点:最大的区别是是否允许其他线程唤醒您。使用“等待”,您可以等待“锁定”对象,他们可以通知它让您提前结束睡眠。使用 sleep() 他们需要引用睡眠线程本身来打断你。
    • @Ry4an 不,我的意思是,我想暂停一个线程 x 秒,没有人会叫醒我。所以我可以Object.wait(timeout),也可以Thread.sleep(timeout)。我如何决定使用哪个?
    • 第三次:都可以。如果您不需要另一个线程来中断睡眠/等待,那么它们实际上是相同的。
    【解决方案2】:

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

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

    第二,神话般的虚假唤醒,如 Java 6 API javadoc 中所述:

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

    虽然不太可能,但每段使用 Object.wait() 的代码都应该考虑到这一点。

    【讨论】:

    【解决方案3】:

    您说为此使用等待/通知是“显然”不好的形式,但我认为它没有任何问题。诚然,通过sleep 调用来跟进它是非常奇怪的(并且吞下异常是不好的),但我之前肯定将Object.wait 用作“易碎的睡眠”。

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

    【讨论】:

    • 恕我直言,在这种情况下这是不好的形式,因为等待发生在 while 循环之外。
    • @Jacques:如果您在问题中说明了这一点,那将会很有帮助。你呈现的只是一个 sn-p - 所以你呈现的不是“明显不好的形式”。即使没有 while 循环,基本上作为“易于取消的计时器”也是合理的。
    • 我很抱歉。基本上你看到的所有代码都在一个类的方法中。 lock 是类的成员变量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-15
    • 2010-09-25
    • 2017-06-25
    • 2023-04-10
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多