什么是Java相当于ManualResetEvent?

时间:2009-06-30 16:09:38

标签: java .net multithreading synchronization

什么是java相当于ManualResetEvent

5 个答案:

答案 0 :(得分:27)

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 boolean waitOne(long milliseconds) throws InterruptedException {
    synchronized (monitor) {
      if (open) 
        return true;
      monitor.wait(milliseconds);
        return open;
    }
  }

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

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

答案 1 :(得分:19)

我最接近的是Semaphore。只需使用“许可”计数为1,而获取/发布将与您在ManualResetEvent中所知的几乎相同。

  

信号量初始化为1,和   这是使用它只有在   大多数可用的许可证,可以服务   作为互斥锁。这是   通常称为二进制   信号量,因为它只有两个   州:一个许可证可用,或零   许可证。在此使用时   方式,二进制信号量有   财产(不像很多锁   实现),“锁”可以   由除以外的线程释放   所有者(因为信号量没有概念   所有权)。这在一些人中很有用   专门的上下文,例如死锁   回收

答案 2 :(得分:8)

尝试CountDownLatch,数量为一。

CountDownLatch startSignal = new CountDownLatch(1);

答案 3 :(得分:3)

基于:

  

ManualResetEvent允许线程通过相互通信   信号。通常,这   沟通涉及一项任务   一个线程必须先完成其他线程   线程可以继续。

从这里开始:

http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx

你可能想看看Java并发包中的障碍 - 特别是 CyclicBarrier 我相信:

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

它会阻止固定数量的线程,直到发生特定事件。所有线程必须在屏障点汇集在一起​​。

答案 4 :(得分:2)

我相信.NET MRE的关键在于线程亲和性以及它在调用Set时允许所有等待线程通过的能力。我发现Semaphore的使用效果很好。但是,如果我等待10或15个线程,那么我会遇到另一个问题。具体来说,它在调用Set时发生。在.Net中,所有等待的线程都被释放。使用semphore不会全部释放。所以我把它包装在一堂课中。注意:我对.NET线程非常熟悉。我是Java线程和同步的新手。不过,我愿意跳进去获得一些真实的反馈。这是我的实现,假设是Java新手所做的:

public class ManualEvent {
private final static int MAX_WAIT = 1000;
private final static String TAG = "ManualEvent"; 
private Semaphore semaphore = new Semaphore(MAX_WAIT, false);

private volatile boolean signaled = false;
public ManualEvent(boolean signaled) {
    this.signaled = signaled; 
    if (!signaled) {
        semaphore.drainPermits();
    }
}

public boolean WaitOne() {
    return WaitOne(Long.MAX_VALUE);
}

private volatile int count = 0;
public boolean WaitOne(long millis) {
    boolean bRc = true;
    if (signaled)
        return true;

    try {
        ++count;
        if (count > MAX_WAIT) {
            Log.w(TAG, "More requests than waits: " + String.valueOf(count));
        }

        Log.d(TAG, "ManualEvent WaitOne Entered");
        bRc = semaphore.tryAcquire(millis, TimeUnit.MILLISECONDS);
        Log.d(TAG, "ManualEvent WaitOne=" + String.valueOf(bRc));
    }
    catch (InterruptedException e) {
        bRc = false;
    }
    finally {
        --count;
    }

    Log.d(TAG, "ManualEvent WaitOne Exit");
    return bRc;
}

public void Set() {
    Log.d(TAG, "ManualEvent Set");
    signaled = true;
    semaphore.release(MAX_WAIT);
}

public void Reset() {
    signaled = false;
    //stop any new requests
    int count = semaphore.drainPermits();
    Log.d(TAG, "ManualEvent Reset: Permits drained=" + String.valueOf(count));
}

}

另请注意,我基本上认为在任何给定时间等待释放的请求不超过1000个。通过批量发布和获取,我试图释放任何等待的线程。请注意,对WaitOne的调用一次只允许1个。