简体   繁体   English

Java等效的.NET的ManualResetEvent和WaitHandle

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

I would like to know if Java provides an equivalent of .NET's classes of ManualResetEvent and WaitHandle, as I would like to write code that blocks for a given timeout unless an event is triggered. 我想知道Java是否提供了类似于.NET的ManualResetEvent和WaitHandle类,因为我想编写阻止给定超时的代码,除非事件被触发。

The .NET classes of WaitHandle and ManualResetEvent provide a nice, hassle-free interface for that which is also thread-safe as far as I know, so what does Java has to offer? WaitHandle和ManualResetEvent的.NET类为我提供了一个很好的,无障碍的接口,据我所知也是线程安全的,所以Java提供了什么?

Have you considered using wait / notify (the equivalent of Monitor.Wait and Monitor.Pulse ) instead? 您是否考虑过使用wait / notify (相当于Monitor.WaitMonitor.Pulse )?

You'll want a little bit of checking to see whether you actually need to wait (to avoid race conditions) but it should work. 你需要进行一些检查,看看你是否真的需要等待(以避免竞争条件),但它应该有效。

Otherwise, something like CountDownLatch may well do what you want. 否则,像CountDownLatch这样的东西可能会做你想要的。

EDIT: I've only just noticed that CountDownLatch is basically "single use" - you can't reset the count later, as far as I can see. 编辑:我刚刚注意到CountDownLatch基本上是“单次使用” - 据我所知,你以后无法重置计数。 You may want Semaphore instead. 您可能需要Semaphore Use tryAcquire like this to wait with a timeout: 像这样使用tryAcquire等待超时:

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

Note that this is unlike ManualResetEvent in that each successful call to tryAcquire will reduce the number of permits - so eventually they'll run out again. 请注意,这与ManualResetEvent不同,每次成功调用tryAcquire都会减少许可数量 - 所以最终它们会再次耗尽。 You can't make it permanently "set" like you could with ManualResetEvent . 您不能像使用ManualResetEvent那样永久地“设置”它。 (That would work with CountdownLatch , but then you couldn't "reset" it :) (那可以使用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;
  }
}

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

Hi, you can achieve synchronization using the java.util.concurrent.Semaphore class (use 0 permit). 嗨,您可以使用java.util.concurrent.Semaphore类实现同步(使用0 permit)。

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

Example below shows you how to solve the first sync problem, the other will be similar: 下面的示例显示了如何解决第一个同步问题,另一个将类似:

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
       //...
   }
}

In theory, the ManualResetEvent class as given above is correct on Java 5 (but not earlier). 理论上,上面给出的ManualResetEvent类在Java 5上是正确的(但不是更早)。 Given the long history of incorrect (or inadequate) implementations of volatile, it seems wiser to me to add an additional synchronized block in reset() in order to generate a guaranteed write barrier, and ensure complete atomicity. 鉴于volatile的不正确(或不充分)实现的悠久历史,我在reset()中添加一个额外的同步块似乎更明智,以便生成有保证的写屏障,并确保完整的原子性。 The danger is that a read of "open" may pass a write of "open" on multi-processor Intel cpus. 危险在于读取“开放”可能会在多处理器Intel cpus上写入“open”。 The advantage of the change given below: it may not be optimally efficient, but it does have the great advantage of being guaranteed to be not wrong, at very little additional cost. 下面给出的改变的优点是:它可能不是最佳效率,但它确实具有保证没有错误的巨大优势,而且成本非常低。

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

Thanks to the original poster. 感谢原始海报。

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

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