This question already has an answer here:
- Java Equivalent of .NET's ManualResetEvent and WaitHandle 4 answers
What is java's equivalent of ManualResetEvent?
This question already has an answer here:
What is java's equivalent of ManualResetEvent?
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
.
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.
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;
}
}
Try CountDownLatch with count of one.
CountDownLatch startSignal = new CountDownLatch(1);
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.
from here:
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 CyclicBarrier I believe:
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.
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:
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.