什么是 java 的 ManualResetEvent 等价物?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1064596/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 15:00:49  来源:igfitidea点击:

What is java's equivalent of ManualResetEvent?

java.netmultithreadingsynchronization

提问by ripper234

What is java's equivalent of ManualResetEvent?

什么是 java 的ManualResetEvent等价物?

采纳答案by Lucero

The closest I know of is the Semaphore. Just use it with a "permit" count of 1, and aquire/release will be pretty much the same as what you know from the ManualResetEvent.

我所知道的最接近的是Semaphore。只需将它的“许可”计数设为 1,获取/释放将与您从ManualResetEvent.

A semaphore initialized to one, and which is used such that it only has at most one permit available, can serve as a mutual exclusion lock. This is more commonly known as a binary semaphore, because it only has two states: one permit available, or zero permits available. When used in this way, the binary semaphore has the property (unlike many Lock implementations), that the "lock" can be released by a thread other than the owner (as semaphores have no notion of ownership). This can be useful in some specialized contexts, such as deadlock recovery.

初始化为 1 的信号量,并且使用时最多只有一个许可可用,可以用作互斥锁。这通常被称为二进制信号量,因为它只有两种状态:一种许可可用,或零许可可用。当以这种方式使用时,二进制信号量具有属性(与许多 Lock 实现不同),即“锁”可以由所有者以外的线程释放(因为信号量没有所有权的概念)。这在某些特定上下文中很有用,例如死锁恢复。

回答by user249654

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

回答by crafty

Try CountDownLatchwith count of one.

尝试计数为 1 的CountDownLatch

CountDownLatch startSignal = new CountDownLatch(1);

回答by Jon

Based on:

基于:

ManualResetEvent allows threads to communicate with each other by signaling. Typically, this communication concerns a task which one thread must complete before other threads can proceed.

ManualResetEvent 允许线程通过信号相互通信。通常,此通信涉及一个线程必须在其他线程继续进行之前完成的任务。

from here:

从这里:

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

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

you possibly want to look at the Barriers in the Java concurrency package - specifically CyclicBarrierI believe:

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

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

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

It blocks a fixed number of threads until a particular event has occured. All the threads must come together at a barrier point.

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

回答by deltaearl

I believe the crux of the .NET MRE is thread affinity and its ability to let all waiting threads go through when Set is called. I found the use of the Semaphore works well. However, if I get 10 or 15 threads waiting, then I run into another issue. Specifically, it occurs when Set is called. In .Net, all waiting threads are released. Using a semphore does not release all. So I wrapped it in a class. NOTE: I am very familiar with .NET threading. I am relatively new to Java threading and synchronization. Nevertheless, I am willing to jump in and get some real feedback. Here's my implementation with assumptions that a Java novice would make:

我相信 .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));
}

}

}

Also note that I am basically betting that there's no more than a 1000 requests waiting for a release at any given time. By releasing and aquiring in batches, I am attempting to release any waiting threads. Note the call to WaitOne is working 1 permit at a time.

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