Java等效的.NET的ManualResetEvent和WaitHandle

时间:2010-09-02 09:58:00

标签: c# java .net eclipse synchronization

我想知道Java是否提供了相当于.NET的ManualResetEvent和WaitHandle类,因为我想编写阻止给定超时的代码,除非事件被触发。

WaitHandle和ManualResetEvent的.NET类为我提供了一个很好的,无障碍的接口,据我所知也是线程安全的,那么Java提供了什么?

4 个答案:

答案 0 :(得分:14)

您是否考虑过使用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,但是你无法“重置”它:)

答案 1 :(得分:4)

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;
  }
}

答案 2 :(得分:2)

来自: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
       //...
   }
}

答案 3 :(得分:1)

理论上,上面给出的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;
        }
      }
   }

感谢原版海报。