我想要实现 未来。获得(长,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年)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top