我读过你应该放的 Object.wait()
在while循环中调用Java。原因是这个线程可能被唤醒,你等待通知的条件仍然是假的(虚假的唤醒)。
关于什么 Object.wait(long timeout)
。在这里,您不希望循环该条件,因为您希望它在指定的时间后超时。但是如果你不把它放在一个循环中那么你怎么能确保它不会被提前唤醒呢?
我读过你应该放的 Object.wait()
在while循环中调用Java。原因是这个线程可能被唤醒,你等待通知的条件仍然是假的(虚假的唤醒)。
关于什么 Object.wait(long timeout)
。在这里,您不希望循环该条件,因为您希望它在指定的时间后超时。但是如果你不把它放在一个循环中那么你怎么能确保它不会被提前唤醒呢?
但是如果你不把它放在一个循环中那么你怎么能确保它不会被提前唤醒呢?
这是Java IMO的一个缺陷,尽管它可能是各种OS变量中底层线程支持的缺陷。我怀疑Java知道等待是否超时,但是如果不重新测试条件并专门测试时间,调用者就无法弄明白。丑陋。
所以你需要把它 wait(long timeout)
在一个 while
循环以及 也 测试时间是否超过超时时间。我知道没有别的方法可以做到这一点。
long timeoutExpiredMs = System.currentTimeMillis() + timeoutMs;
while (!condition) {
long waitMs = timeoutExpiredMs - System.currentTimeMillis();
if (waitMs <= 0) {
// timeout expired
break;
}
// we assume we are in a synchronized (object) here
object.wait(waitMs);
// we might get improperly awoken here so we loop around to see if we timed out
}
但是如果你不把它放在一个循环中那么你怎么能确保它不会被提前唤醒呢?
这是Java IMO的一个缺陷,尽管它可能是各种OS变量中底层线程支持的缺陷。我怀疑Java知道等待是否超时,但是如果不重新测试条件并专门测试时间,调用者就无法弄明白。丑陋。
所以你需要把它 wait(long timeout)
在一个 while
循环以及 也 测试时间是否超过超时时间。我知道没有别的方法可以做到这一点。
long timeoutExpiredMs = System.currentTimeMillis() + timeoutMs;
while (!condition) {
long waitMs = timeoutExpiredMs - System.currentTimeMillis();
if (waitMs <= 0) {
// timeout expired
break;
}
// we assume we are in a synchronized (object) here
object.wait(waitMs);
// we might get improperly awoken here so we loop around to see if we timed out
}
long deadline = now() + timeout;
synchronized(lock)
while( !condition() && now()<deadline )
lock.wait( deadline - now() );
if(condition())
...
else // timeout
...
这是因为java有Mesa风格的显示器而不是Hoare风格的显示器。所以你需要等待一段时间。 请搜索字符串“因此,通常需要在下面的网页中将每个等待操作包含在这样的循环中”,
http://en.wikipedia.org/wiki/Monitor_(synchronization)#Nonblocking_condition_variables
如果它是Hoare风格的显示器,那么你可以放弃等待。我将很快添加Mesa监视器的详细信息。这不是Java的缺陷。两种类型的监视器都有优点和缺点。
在循环中调用等待不仅仅是为了处理偶尔的虚假唤醒。在一般(非玩具示例)情况下,多个线程争用锁定,当一个线程从等待中醒来时,它在等待之前所做的任何检查都不足以预测该对象所处的状态。那个等待的人已经放弃了锁定,所以从那时起就发生了任何事情,而且关于通知如何工作没有任何原子,只是因为你得到通知并不意味着另一个线程没有在通知发出之间的时间内潜入并且通知的线程重新获得锁定。
从根本上说,你需要在循环中等待,因为你需要通过锁定来检查当前状态,以便能够分辨出正在发生的事情。超时不会改变这一点。超时是一种安全机制,因此如果错过通知,线程将永远不会挂起。如果等待时间通常不需要任何特定操作,只需重新获取锁定,继续循环体,并像往常一样检查thr条件。
这不是Java的错,这就是pthreads的工作方式。