morizn said:
thanks for your answer. you're right, i could have pointed out more
exactly what my problem is. look at the following code:
I'm looking:
Don't do that. When you catch Exception, you are catching an incredibly
large class of erro conditions, many of which you certainly don't
understand. Instead, if you wish to catch IllegalMonitorStateException
and InterruptedException, then catch those types, and let all other
exceptions true. (My suspicion, though, is that you really don't want
to catch IllegalMonitorStateException at all. See below.)
If you do enough of the kind of catch block above, you will end up
writing programs that don't crash because you've caught the exception,
but do corrupt data because you didn't recover from the exception. If
the program crashes, the user only has to run it again. If it corrupts
data, you could cost the user thousands of dollars or more trying to
recover. The user will then curse your name for all of eternity. I'm
told it's no fun to have someone cursing your name for all of eternity.
It's always better to crash than to corrupt data. Even code posted to
this newsgroup is imitated by people learning Java, and then makes it's
way into production, causing the above mentioned name-cursing.
if i remove the synchronized around the wait in the receiver thread, it
doesn't wait at all.
Right. It throws IllegalMonitorStateException, which you then catch and
ignore so that it *looks* like it just didn't wait. I presume from
context that you knew this already?
i do know that only one thread can get into the monitor of sync at one
time. but what do the monitors have to do with the wait method? why did
the java developers expect the wait method to be inside a synchronized
statement?
You need to be in a 'synchronized' block to wait() and notify() because
otherwise it's impossible to use the methods correctly. You would
always end up with a race condition between the waiting thread and the
notifying thread, where the notifying thread could call notify() just
moments *before* the waiting thread sleeps, and you lose a signal. To
avoid that, you need to use synchronized *AND* a predicate. You are
halfway there.
The predicate is, simply put, what you are waiting for. The notifying
thread first sets the predicate, and then sends the notification. The
waiting thread first checks the predicate, and then waits only if it has
something to wait for. When it's done waiting, it checks the predicate
again to be sure that it has really finished waiting. This is generally
accomplished with a while loop.
To revise your code:
public class Test
{
/* The predicate for the sample wait/notify below. */
public static boolean avail = 0;
public static void main(String[] args)
{
Object sync = new Object();
new Receiver(sync);
new Sender(sync);
}
}
class Sender extends Thread
{
Object sync;
public Sender(Object s)
{
sync = s;
start();
}
// generating a Signal
public void run()
{
for (int i=0; i<10; i++)
{
try
{
sleep(1000);
synchronized (sync)
{
Test.avail++;
sync.notifyAll();
}
}
catch (InterruptedException e)
{
}
}
}
}
class Receiver extends Thread
{
Object sync;
public Receiver(Object s)
{
sync = s;
start();
}
public void run()
{
while (true)
{
synchronized (sync)
{
while (Test.avail == 0) sync.wait();
Test.avail--;
}
System.out.println("Signal Received.");
}
}
}
As for IllegalMonitorStateException, if it occurs then you have a bug in
your code. There is no possible user input or normal error condition
that should be able to cause your program to throw an
IllegalMonitorStateException. For that reason, you almost certainly
don't want to catch it; and if you do catch it, you certainly don't want
to ignore it. You need to abort the entire operation you're working on
(which might be the entire program) to the point that you're certain
that the state of the application is consistent again.
You also need to log the exception so that you get some kind of
indication of this bug. Depending on how much control you have over the
client, I've even sometimes included the ability to email a bug report,
so that I really do find out when these things occur if the user is okay
with it.
--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation