有这个等待声明:
public final native void wait(long timeout) throws InterruptedException;
它可能会被InterruptedException或超时退出,或者因为Notify / NotifyAll方法在另一个线程中被调用,所以Exception很容易被捕获但是......
有什么方法可以知道退出原因是超时还是通知?
修改
这是一种可行的方法,(虽然我不喜欢)
long tBefore=System.currentTimeMillis();
wait(TIMEOUT);
if ((System.currentTimeMillis() - tBefore) > TIMEOUT)
{
//timeout
}
答案 0 :(得分:15)
还有一个原因是通知可以返回:虚假唤醒。这是不太可能但可能的事情,因为在某些硬件/操作系统组合上防止虚假唤醒是非常昂贵的。
因此,您必须在循环中调用wait()并重新检查您正在等待的条件。在这项工作中,很容易同时检查超时。
有关详细信息,我建议使用“Java Concurrency In Practice”一书。并使用更高级别的结构,这将使你正确。
答案 1 :(得分:12)
这并不完全回答这个问题,但它可能会解决您的问题:使用更高级别的并发机制。由于这个原因,等待/通知通常比你想要的更低级。
例如,如果您使用BlockingQueue.poll(long, TimeUnit)
,则可以检查结果是否为空,以了解您是否超时。
答案 2 :(得分:10)
除非您提供一些额外的代码,否则无法区分这两者。例如,仅在ThreadLocal
上添加Boolean
设置为true
的{{1}}
但首先,你必须确保你的逻辑需要这种差异化。
答案 3 :(得分:4)
请勿使用System.currentTimeMillis()
,而是使用System.nanoTime()
。
第一个确定绝对时间(基于系统时钟),如果系统时间改变,可能会产生奇怪的结果。例如:如果时钟向后移动一小时,则5秒等待可以持续一小时,如果时钟向前移动,则在0秒后等待10分钟。
第二个是相对时间。它总是以一个恒定的速度在一个方向上运行,但它没有原点。这意味着这些值只能用于确保相对时间,但可以而且不应该用于确定日期。
答案 4 :(得分:2)
没有办法直接告诉 - 也就是说,您必须添加其他代码来确定这一点。通常当你等待()时,你正在等待某些事情发生,这会以某种方式改变对象的状态 - 例如通过设置一个布尔变量,也许。如果是这种情况,那么您可以简单地检查该变量的状态以查看事件是否发生,或者您只是超时。或者你可以查看System.currentTimeMillis()的值,看看我经过的时间是否大于或等于超时时间 - 如果是,这可能是你可能已经超时的线索(尽管这不是绝对的保证) )。或者如果经过的时间小于超时时间,那么你当然没有超时。这有帮助吗?
答案 5 :(得分:1)
通知和超时时不会抛出异常。
我认为最好依赖java.lang.concurrent
包同步对象而不是Object.wait()
。
答案 6 :(得分:0)
您应该使用不等待/通知方法。
它已经超时等待,如果从方法返回之前可以检测到等待时间,则返回false,否则返回true。