2010-08-03 61 views
19

有了这个等待声明:如何区分等待(超时超时)退出通知或超时?

public final native void wait(long timeout) throws InterruptedException; 

它可以通过InterruptedException的退出,或超时,或因为通知/ notifyAll的方法被调用在另一个线程,异常是容易赶上,但...

有有什么方法可以知道退出原因是超时还是通知?

编辑:

这是一个可以工作,(虽然我不喜欢它),除非你提供一些额外的你无法区分这两种一个取巧的办法

  long tBefore=System.currentTimeMillis(); 
      wait(TIMEOUT); 
      if ((System.currentTimeMillis() - tBefore) > TIMEOUT) 
      { 
       //timeout 
      } 
+2

我也有类似的需求,并在我的情况下,它变成了一个'Semaphore'更适合; 'Semaphore.tryAcquire(long timeout,TimeUnit unit)'如果超时已过,则返回'false'。 – Santosh 2017-06-24 10:52:00

+0

信号灯会工作,除非你需要有等待其不被信号量公共合同支持的能力。 – 2017-12-22 05:33:25

回答

7

码。例如通过增加ThreadLocalBoolean被设置为truenotify()

但首先你必须确保你的逻辑需要这种分化。

+4

OP已经知道一个异常不会被抛出,并希望区分超时和通知。这没有提供任何有用的信息,为此。 – 2010-08-03 15:04:14

+1

谢谢,我误解了OP。现在更新。 – Bozho 2010-08-03 19:19:56

+0

+1用于重写,并且是布尔值同步方法是我现在使用的方法 – 2010-08-04 11:21:04

1

异常不会引发通知和超时。

我认为最好依靠java.lang.concurrent包同步对象而不是使用Object.wait()

12

这并不完全回答问题,但它可能会解决您的问题:使用更高级别的并发机制。由于这个原因,等待/通知通常比你想要的更低级别。

例如,如果您使用的是BlockingQueue.poll(long, TimeUnit),则可以检查结果是否为空以知道您是否超时。

16

还有一个原因是通知可以返回:虚假唤醒。这是不太可能的,但可能的事情,因为防止虚假唤醒在某些硬件/操作系统组合上非常昂贵。

因此,您总是必须在循环中调用wait()并重新检查您正在等待的条件。在这项工作中,很容易同时检查超时。

有关详细信息,我推荐“Java并发实践”一书。并使用更高层次的结构,这将使你的这一切都正确。

+0

+1我会在帐户那些虚假唤醒 – 2010-08-03 15:46:23

2

无法直接告知 - 也就是说,您必须添加额外的代码才能确定这一点。通常当你等待()时,你正在等待某些事情发生,以某种方式改变对象的状态 - 例如,通过设置一个布尔变量,也许。如果是这种情况,那么您可能只需检查该变量的状态以查看事件是否发生,或者您只是超时。或者你可以看看System.currentTimeMillis()的值来查看经过时间是否大于或等于超时时间 - 如果是,那可能是你可能已超时的线索(尽管这不是绝对的保证)。或者如果经过的时间少于超时时间,那么你肯定没有超时。这有帮助吗?

+0

我实际上使用currentTimeMillis(),但我想知道是否有一些更好的方法 – 2010-08-03 15:26:37

+0

@HernánEche因为我已经把我的答案并不绝对保证。如果你可以告诉,为什么你要确定它是否超时?我们可以寻找一些解决方案。 – YoK 2010-08-03 15:32:48

+0

是的,我知道这不是一个很好的方法,我用它作为循环while(true){wait(timeout);其他任务..; }所以它可以退出循环,当等待真正得到通知,例如,如果等待将返回布尔值,它会像while(true){if(wait(timeout))break;其他任务..; }无论如何,我将它封装在一个类和一个标志与同步方法等待/通知与此标志的设置并行 – 2010-08-03 15:59:59

3

请勿使用System.currentTimeMillis(),请使用System.nanoTime()代替。

第一个meassures绝对时间(根据系统时钟),如果系统时间更改可能会好奇的结果。例如:如果该时钟由一个小时向后移动,或有10分钟的等待将0秒后,如果时钟移动foreward进行5秒的等待可以有一个小时的持续时间。

第二个meassures相对时间。它总是以恒定的速度在一个方向运行,但它没有起源。这意味着这些值只能用于确定相对时间,但可以并不应该用于确定日期。