You want to use a counting semaphore. Condition variables are meant for scheduling threads inside a monitor. This is not what your trying to do.
You create a counting semaphore and set the count to zero
// create a counting semaphore with an initial count of zero
java.util.concurrent.Semaphore s = new java.util.concurrent.Semaphore(0);
You pass the semaphore to your class the does the processing. When it is finished, it increasing the count to 1 by calling s.release()
.
To block a thread until the processor is finished, you call s.aquire()
. That call will cause your other thread to block until the processor calls s.release()
.
This is the simplest solution.
Btw, s.aquire()
and s.release()
are thread safe, so you don't need to use the synchronize keyword. Threads can share references to a semaphore and call its methods without locking.
UPDATE:
I'm going to respond to your comment here instead of making a new comment.
Yes, in your case a wait()/notify() solution is similar to using a semaphore. To rewrite rsp's solution with a semaphore, it would look like:
java.util.concurrent.Semaphore s = new java.util.concurrent.Semaphore(0);
public setDone() {
s.release();
}
public waitUntilDone() {
s.aquire();
}
It is much simpler and you don't need an unnecessary lock (notice i removed the synchronized keyword from the method decs.).
There are 2 differences between condition variables (wait()/notify()) and semaphores.
Difference #1: calls to notify() may be lost, calls to release() are never lost
The first difference is that calls to notify() are are lost if there is no thread waiting via a call to wait(). The work around is to check the condition before calling wait(). Basically, we need to remember that notify() was called with a shared variable so we don't accidentally call wait() after the worker calls notify(), or else we deadlock. Counting semaphores work no matter the order in which acquire() and release() are called because they maintain a count inside.
Difference #2: calls to wait() automatically release a lock, calls to acquire() do not
Some background information will help here. In your program the boolean done = false;
variable is the condition, but it isn't the condition variable. Confusing terminology, I know. The condition variable is the variable that has operations wait() and notify(). Every object in Java has a condition variable hidden inside and a corresponding lock.
All condition variables are associated with a lock. You must acquire the lock before you can call wait() and notify() (you will get a runtime exception if you don't, try it). Once the lock is acquired, calls to wait() automatically release the lock, allowing another thread inside the monitor to possibly call notify(). Sometimes, this is exactly what you want, and trying to simulate this behavior with semaphores will be much more complicated.
Note: I'm using the academic definition of monitor which differs entirely from the Java definition of a monitor.