繁体   English   中英

如何使用TimeUnit.timedWait()而不会损失纳秒精度?

[英]How to use TimeUnit.timedWait() without losing nanosecond precision?

我试图用TimeUnit.timedWait(Object,long)来实现Future.get(long,TimeUnit

目前尚不清楚如何使用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()什么?

在等待之前,请存储要超时的时间。

在通知等待线程之前,设置一些共享(同步)状态信号,表示等待线程应该停止等待,因为计算已完成。

当你的线程因为某种原因从等待中醒来时它应该检查共享状态以查看它是否应该停止等待,并且它还应检查超时到期之前剩余的时间。 如果超时未到期,并且共享状态告诉不说停止等待,那么您应该再次等待(但是使用从当前时间计算的新的较短时间)。

您的问题的答案在于Object.wait(long)规范:

线程也可以在没有被通知,中断或超时的情况下唤醒,即所谓的虚假唤醒。 虽然这在实践中很少发生,但应用程序必须通过测试应该导致线程被唤醒的条件来防范它,并且如果条件不满足则继续等待。 换句话说,等待应该总是出现在循环中,如下所示:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait(timeout);
     ... // Perform action appropriate to condition
 }

(有关该主题的更多信息,请参阅Doug Lea的“Java中的并发编程(第二版)”(Addison-Wesley,2000)中的第3.2.3节,或Joshua Bloch的“Effective Java Programming Language Guide”中的第50项(Addison-韦斯利,2001年)。

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不容易受到虚假唤醒的影响 (因为它可以在返回之前检查内部的锁存状态)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM