wait(), sleep() and notify()
Let's say I call Thread.currentThread().wait(), then a couple of lines down I call Thread.currentThread().sleep(2000) in a while loop.
Several lines after that, if a condition is met, I call Thread.currentThread().notify(). I want to free up one of the threads that were put on wait at the beginning, will the notify() do that? It won't try to wake up a thread that was asleep right?
Also, the thread I put to sleep, I want it to relinquish it's right to the processor for those 2 seconds so that another thread can get a chance to check the condition for the loop and maybe continue further. Will putting it to sleep do that?
Re: wait(), sleep() and notify()
wait() and notify() are mechanisms for synchronization. They're used differently than sleep, who's use in a multi-threaded application is discouraged because the thread doesn't actually release any locks it owns, creating the potential for deadlocks and other nasty stuff. I've never tried mixing the two together.
wait() and notify() work inside of synchronized methods/blocks, and generally I wouldn't recommend using them on the Thread object, rather you should determine which resource you want to release and wait to re-acquire.
Here's a simple worker pool example. The worker will wait for someone to give it a task, or tell it to stop. Since locks are associated with objects, not variables, the best way to handle locks is to synchronize on the WorkerA object itself. I could create a specific lock object, but that really isn't necessary here.
Code java:
class Worker implements Runnable
{
private Runnable task;
private boolean keep_running;
public Worker()
{
keep_running = true;
}
public synchronized void run()
{
while(keep_running)
{
wait(); // wait for someone to give us a task or tell us to stop
if(keep_running && task != null)
{
task.run();
}
}
}
/**
* Assigns this worker to perform task t
*/
public synchronized start_task(Runnable t)
{
task = t;
notify();
}
/**
* Finishes the current task and then stops the worker
*/
public synchronized finish()
{
keep_running = false;
notify();
}
}
Re: wait(), sleep() and notify()
Ok, let's say I don't use sleep(). Here's what I'm trying to do and can't seem to figure out the way.
I create n number of threads
in the run() method:
if(function returns false){
synchronized(this)
wait();
else
do some action
.
.
.
while(function returns false){
synchronized(this)
wait(2000) <- wait 2 seconds then check condition again.
}
do some action
finish actions
synchronized(this)
notify() <- I want to notify the threads in the first wait()
Re: wait(), sleep() and notify()
Looks like it should work in theory, though it doesn't look it acquires/holds the lock during any useful operations other than to use wait/notify. This might work because you may not have any need for any other synchronization.
For example, take a look at my run method above:
Code java:
public synchronized void run()
{
while(keep_running)
{
wait(); // wait for someone to give us a task or tell us to stop
if(keep_running && task != null)
{
task.run();
}
}
}
notice that my program holds onto the lock while it's running the task. This means that any other thread which is trying to run a task with this worker will wait until it can acquire the lock, guaranteeing that all tasks get run. On the other hand, say I try doing this:
Code java:
public void run()
{
while(keep_running)
{
synchronized(this)
{
wait(); // wait for someone to give us a task or tell us to stop
}
if(keep_running && task != null)
{
task.run();
}
}
}
This means any other thread which wants the Worker to perform a task will always be able to modify the task variable, and with multiple tasks being assigned it's not even guaranteed that all tasks will run. Additionally the notify() might not even have any effect since my run method must be in a wait() state before notify() is called. These are race conditions which are highly dependent on the timing of what code is executed, which are extremely difficult to debug since the behavior is dependent on timing. For example, I once worked on a project where the code had a race condition. It so happened to be that when I ran the program in debug mode it worked exactly as we wanted it to. However, when run in release mode the timing was just different enough that the program would do things in all the wrong order and fail to function properly.