如何使用TimeUnit.timedWait()没有失去纳秒的精确?
-
21-09-2019 - |
题
我想要实现 未来。获得(长,TimeUnit) 在条款 TimeUnit.timedWait(目的,长).
还不清楚如何使用 TimeUnit.timedWait(Object, long)
在一的方式处理"虚拟"唤醒而不会失去毫微秒的组成部分TimeUnit.通常情况下你会怎么做事情是这样的:
public V get(long timeout, TimeUnit unit)
{
long expirationTime = new Date().getTime() + unit.toMillis(timeout);
while (!condition)
{
long timeLeft = expirationTime - new Date().getTime();
if (timeLeft <= 0)
throw new TimeoutException();
unit.timedWait(object, timeLeft);
}
}
但你失去了纳秒的组成部分。如果每个人都是简单地删除毫微秒组然后点是什么 TimeUnit
甚至支持纳秒并提供 TimeUnit.timedWait()
?
解决方案 3
CountDownLatch 似乎是实现这个的最简单的方法:
public class MutableFuture<T> implements Future<T>
{
private final CountDownLatch done = new CountDownLatch(1);
private T value;
private Throwable throwable;
public synchronized boolean isDone()
{
return done.getCount() == 0;
}
public synchronized T get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException
{
if (!done.await(timeout, unit))
throw new TimeoutException();
if (throwable != null)
throw new ExecutionException(throwable);
return value;
}
// remaining methods left as exercise to the reader :)
}
CountdownLatch不易受到杂散唤醒(因为它可以在内部返回之前检查所述闩锁状态)。
其他提示
在等待之前,存储在要超时的时间。
之前通知等待线程,设置一些共享(同步)状态信令,所述等待线程应该停止等待,因为计算完成。
当你的线程不管出于什么原因,应该检查共享状态,看它是否应该停止等待,而且还应该检查超时到期之前多长时间留在等待唤醒。如果超时尚未到期,共享状态告知没有说停止等待,那么你应该再等待(但使用了从当前时间计算出一个新的更短的时间)。
回答你的问题在于 对象。等(long) 规格:
一个线程可以也醒来没有被通知,中断,或时,所谓的虚假唤醒。虽然这会很少发生在实践中,申请必须防止它通过的测试条件下,应已经造成线被唤醒,并继续等待,如果情况不满意。换句话说,等待,应该总是发生在循环,这样一:
synchronized (obj) {
while (<condition does not hold>)
obj.wait(timeout);
... // Perform action appropriate to condition
}
(欲了解更多有关这一主题,请参阅第3.2.3在Doug Lea的"并发的编程在Java(第二版)"(Addison-Wesley,2000),或者项目50约书亚布洛赫的"有效Java编程语言编写的指南"(Addison-Wesley,2001年)。