Java 如何区分等待(长时间超时)退出通知或超时?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3397722/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:56:50  来源:igfitidea点击:

How to differentiate when wait(long timeout) exit for notify or timeout?

javamultithreadingwaitsynchronizednotify

提问by Hernán Eche

Having this wait declaration:

有这个等待声明:

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

It could exit by InterruptedException, or by timeout, or because Notify/NotifyAll method was called in another thread, Exception is easy to catch but...

它可能因 InterruptedException、超时或因为 Notify/NotifyAll 方法在另一个线程中被调用而退出,异常很容易捕获,但是......

There is any way to know if the exits cause was timeout or notify?

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

EDIT:

编辑:

This is a tricky way that could work, (although I don't like it)

这是一种可行的棘手方法,(虽然我不喜欢它)

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

采纳答案by Bozho

You can't differentiate between the two unless you provide some additional code. For example by adding a ThreadLocalBooleanthat is set to trueonly on notify()

除非您提供一些额外的代码,否则您无法区分两者。例如,通过添加ThreadLocalBoolean设置为true仅打开notify()

But first you must make sure your logic requires this differentiation.

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

回答by Manuel Selva

Exception is not thrown on notify and time out.

通知和超时不会抛出异常。

I think it's better to rely on java.lang.concurrentpackage synchronisation objects instead of using Object.wait().

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

回答by Mark Peters

This doesn't exactly answer the question, but it will probably solve your problem: Use higher level concurrency mechanisms. Wait/notify is usually more low-level than you'd want, for this reason among many others.

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

For example, if you were using BlockingQueue.poll(long, TimeUnit), you could check if the result is null to know if you timed out.

例如,如果您正在使用BlockingQueue.poll(long, TimeUnit),您可以检查结果是否为空以了解您是否超时。

回答by Darron

There is one more reason that notify can return: spurious wakeup. This is an unlikely but possible thing, because preventing spurious wakeups is very expensive on some hardware/OS combinations.

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

Because of this you always have to call wait() in a loop and re-check the condition that you are waiting for. During this work it's easy to check for timeout at the same time.

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

For details I recommend the book "Java Concurrency In Practice". And using higher level constructs that will get this all correct for you.

有关详细信息,我推荐“Java Concurrency In Practice”一书。并使用更高级别的构造,这将为您提供所有正确的信息。

回答by YoK

There's no way to tell directly- that is, you would have to add additional code to determine this. Often when you wait(), you're waiting for something to happen which changes the state of an object in some way - e.g. by setting a boolean variable, perhaps. If that's the case, then you may be able to simply check the state of that variable to see if the event occurred, or you merely timed out. Or you can look at the value of System.currentTimeMillis() to see i the elapsed time is greater than or equal to the timeout period - if it is, that would be a clue you have probably timed out (though it's not an absolute guarantee). Or if the elapsed time is less than the timeout period then you certainly have not timed out. Does that help?

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

回答by tobain

Don't use System.currentTimeMillis(), use System.nanoTime()instead.

不要使用System.currentTimeMillis()System.nanoTime()而是使用。

The first one meassures absolute time (based on system clock) and might have curious results if the system time is changed. For example: A 5 second wait can have a duration of an hour if the clock is moved backward by an hour, or a 10 minute wait will be done after 0 seconds if the clock is moved foreward.

第一个测量绝对时间(基于系统时钟),如果系统时间改变,可能会产生奇怪的结果。例如:如果时钟向后移动一个小时,则 5 秒的等待可以持续一个小时,或者如果时钟向前移动 0 秒后将完成 10 分钟的等待。

The second one meassures relative time. It will always run in one direction at constant speed, but it has no origin. That means that the values can only be used to meassure relative time, but can and should not be used to determine a date.

第二个测量相对时间。它将始终以恒定速度向一个方向运行,但它没有原点。这意味着这些值只能用于测量相对时间,但可以也不应该用于确定日期。

回答by Aleksandr Filichkin

You should use not wait/notify approach.

您应该使用不等待/通知方法。

Will be better to use Lock with Condidions https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html#await-long-java.util.concurrent.TimeUnit-

将锁定与条件结合使用会更好https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html#await-long-java.util.concurrent.TimeUnit-

It has await with timeout and will return false if the waiting time detectably elapsed before return from the method, else true

它具有等待超时,如果在从方法返回之前可检测到等待时间已经过去,则返回 false,否则返回 true