Java 中的 ManualResetEvent 等价物是什么? [重复]

问题描述 投票:0回答:5

java 中相当于 ManualResetEvent 的是什么?

java .net multithreading synchronization
5个回答
28
投票
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;
  }
}

20
投票

我所知道的最接近的是信号量。只需将它的“允许”计数设置为 1,获取/释放将与您从

ManualResetEvent
中了解到的几乎相同。

信号量初始化为 1,并且 它的使用使得它只有在 最多可获得一份许可证,可以服务 作为互斥锁。这是 通常称为二进制 信号量,因为它只有两个 州:可获得一份许可证,或零份 可用许可证。当用在这个 方式,二进制信号量有 财产(不像许多锁 实现),“锁”可以 由除 所有者(因为信号量没有 所有权)。这在某些方面可能很有用 专门的上下文,例如死锁 恢复。


10
投票

尝试 CountDownLatch 计数为一。

CountDownLatch startSignal = new CountDownLatch(1);

3
投票

基于:

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

从这里:

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

您可能想查看 Java 并发包中的 Barriers - 特别是 CyclicBarrier 我相信:

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

它会阻塞固定数量的线程,直到发生特定事件。所有的线必须在障碍点处聚集在一起。


2
投票

我相信 .NET MRE 的关键在于线程关联性以及它在调用 Set 时让所有等待线程通过的能力。我发现信号量的使用效果很好。但是,如果有 10 或 15 个线程在等待,那么我就会遇到另一个问题。具体来说,它发生在调用 Set 时。在.Net中,所有等待线程都被释放。使用信号量并不会释放所有内容。所以我把它封装在一个类中。注意:我非常熟悉 .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 个许可证。

© www.soinside.com 2019 - 2024. All rights reserved.