C# Java与.NET的等价物';s ManualResetEvent和WaitHandle

C# Java与.NET的等价物';s ManualResetEvent和WaitHandle,c#,java,.net,eclipse,synchronization,C#,Java,.net,Eclipse,Synchronization,我想知道Java是否提供了与.NET的ManualResetEvent和WaitHandle类等价的类,因为我想编写代码,除非触发事件,否则会在给定的超时时间内阻塞 WaitHandle和ManualResetEvent的.NET类提供了一个很好的、无麻烦的接口,据我所知,它也是线程安全的,那么Java提供了什么呢?您是否考虑过使用wait/notify(相当于Monitor.wait和Monitor.Pulse) 你需要一点检查,看看你是否真的需要等待(以避免比赛条件),但它应该会起作用 否则

我想知道Java是否提供了与.NET的ManualResetEvent和WaitHandle类等价的类,因为我想编写代码,除非触发事件,否则会在给定的超时时间内阻塞


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

您是否考虑过使用
wait
/
notify
(相当于
Monitor.wait
Monitor.Pulse

你需要一点检查,看看你是否真的需要等待(以避免比赛条件),但它应该会起作用

否则,像这样的事情很可能会做你想做的

编辑:我刚刚注意到,
CountDownLatch
基本上是“一次性使用”——据我所知,您以后不能重置计数。你可能会想要。像这样使用
tryAcquire
等待超时:

if (semaphore.tryAquire(5, TimeUnit.SECONDS)) {
   ...
   // Permit was granted before timeout
} else {
   // We timed out while waiting
}
请注意,这与
ManualResetEvent
不同,因为每次成功调用
tryAcquire
都会减少许可证的数量,因此最终它们会再次用完。您不能像使用
ManualResetEvent
一样将其永久“设置”。(这将与倒计时闩锁一起工作,但是您无法“重置”它:)

来自:

您好,您可以使用java.util.concurrent.Semaphore类(使用0 permit)实现同步

下面的示例演示如何解决第一个同步问题,另一个类似:

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 CPU上读取“open”可能会传递写入“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;
        }
      }
   }

多亏了原来的海报

但是超时方面呢?从我在CountDownLatch的文档中读到的内容来看,它似乎没有一个超时值,我可以在超时运行到最后之前拦截或停止它。我希望有一个Java类型,我可以使用它来等待超时,并且可以在超时结束之前拦截它,比如手动覆盖。还有,你好,斯基特先生!你好吗?你可能会得到很多,但你的书很棒@Voulnet:您可以调用
wait(长超时,时间单位)
——它将在给定的超时持续时间内阻塞,或者在锁存器倒计时为0时更早返回。很高兴你喜欢这本书:)是的,这个解决方案一定很有效,因为我在任何时候都只有一个对象在等待。谢谢,Jon Skeet先生。请注意,这包含一个严重的错误:如果在
set()
之前调用
waitOne()
,则将输入
监视器,因此对
set()
的调用将被阻止,从而导致死锁。我的黑客解决方案是在循环中调用
monitor.wait(10)
,该循环每次迭代都会退出同步。实际上,我可能错了,因为显然应该在等待期间释放监视器,尽管我的测试显示出明确的死锁。不管怎样,我已经切换到在我的用例中使用
信号灯
。你能用死锁进行测试吗?事实上,问题是当ManualResetEvent打开时,所有线程都应该唤醒吗?尽管我看起来也很怀疑。可以。
   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;
        }
      }
   }