簡體   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