簡體   English   中英

Java等效的.NET的ManualResetEvent和WaitHandle

[英]Java Equivalent of .NET's ManualResetEvent and WaitHandle

我想知道Java是否提供了類似於.NET的ManualResetEvent和WaitHandle類,因為我想編寫阻止給定超時的代碼,除非事件被觸發。

WaitHandle和ManualResetEvent的.NET類為我提供了一個很好的,無障礙的接口,據我所知也是線程安全的,所以Java提供了什么?

您是否考慮過使用wait / notify (相當於Monitor.WaitMonitor.Pulse )?

你需要進行一些檢查,看看你是否真的需要等待(以避免競爭條件),但它應該有效。

否則,像CountDownLatch這樣的東西可能會做你想要的。

編輯:我剛剛注意到CountDownLatch基本上是“單次使用” - 據我所知,你以后無法重置計數。 您可能需要Semaphore 像這樣使用tryAcquire等待超時:

if (semaphore.tryAquire(5, TimeUnit.SECONDS)) {
   ...
   // Permit was granted before timeout
} else {
   // We timed out while waiting
}

請注意,這與ManualResetEvent不同,每次成功調用tryAcquire都會減少許可數量 - 所以最終它們會再次耗盡。 您不能像使用ManualResetEvent那樣永久地“設置”它。 (那可以使用CountdownLatch ,但是你不能“重置”它:)

class ManualResetEvent {

  private final Object monitor = new Object();
  private volatile boolean open = false;

  public ManualResetEvent(boolean open) {
    this.open = open;
  }

  public void waitOne() throws InterruptedException {
    synchronized (monitor) {
      while (open==false) {
          monitor.wait();
      }
    }
  }

  public void set() {//open start
    synchronized (monitor) {
      open = true;
      monitor.notifyAll();
    }
  }

  public void reset() {//close stop
    open = false;
  }
}

來自: http//www.experts-exchange.com/Programming/Languages/Java/Q_22076798.html

嗨,您可以使用java.util.concurrent.Semaphore類實現同步(使用0 permit)。

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Semaphore.html

下面的示例顯示了如何解決第一個同步問題,另一個將類似:

import java.util.concurrent.Semaphore;

class ScalesCommunication {

   private static Semaphore sem = new Semaphore(0);

   // called by thread 1
   void readLoop() {
      //...

      //after connection established, release semaphore (value incremented by 1)
      sem.release();
   }

   // called by thread 2
   String sendCommand(String command) {

       sem.acquire(); // thread waits here if sem value == 0

       // at this point connection is established
       //...
   }
}

理論上,上面給出的ManualResetEvent類在Java 5上是正確的(但不是更早)。 鑒於volatile的不正確(或不充分)實現的悠久歷史,我在reset()中添加一個額外的同步塊似乎更明智,以便生成有保證的寫屏障,並確保完整的原子性。 危險在於讀取“開放”可能會在多處理器Intel cpus上寫入“open”。 下面給出的改變的優點是:它可能不是最佳效率,但它確實具有保證沒有錯誤的巨大優勢,而且成本非常低。

   class ManualResetEvent {
      private final Object monitor = new Object();
      private volatile boolean open = false;

      public ManualResetEvent(boolean open) {
        this.open = open;   }

      public void waitOne() throws InterruptedException {
        synchronized (monitor) {
          while (open==false) {
              monitor.wait();
          }
        }
      }

      public void set() {//open start
        synchronized (monitor) {
          open = true;
          monitor.notifyAll();
        }
      }

      public void reset() {//close stop
        synchronized(monitor) {
           open = false;
        }
      }
   }

感謝原始海報。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM