This week's book giveaway is in the OCPJP forum. We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line! See this thread for details.
You have discovered an odd effect which is not going to be on the test. It turns out that in Java's Thread implementation, whenever a Thread finishes running, it calls its own notifyAll() method. This allows any other threads that are calling join() to receive a notification and resume running. Because Reader and Calculator both extend Thread directly, they have this behavior, which means they call notifyAll() as soon as their run method ends. Since the notifyAll() shown in the code runs just before run() ends, notifyAll() basically gets called twice in a row. When you comment out one of those calls, the second remains.
Here's an alternate version implementing Runnable rather than extending Thread. This way Calculator and Reader don't inherit the unexpected behavior of Thread. If you comment out the notifyAll(), you will see that no reader ever returns from the wait().
I also added a Thread.sleep() inside Calculator's run() method, to avoid the problem discussed in the next few pages ("Using wait() in a loop"). Without this, you may not always see all three Readers finish.
"I'm not back." - Bill Harding, Twister
Joined: Mar 13, 2008
thank you Jim,
One more question, where can i find information about this strange behavior on java's Thread Implementation ?
Joined: Jan 30, 2000
I'm not sure - this is undocumented trivia, really. You can look at the source code for the Thread class and see that, for example, the join() method contains a wait(), which means that something must send a notify() or notifyAll() when the thread is done. That's how I learned of this. More generally, JLS 17.8.1 says that a thread can have a "spurious wake-up" - meaning it may return from wait() for no apparent reason. This is another reason why you always need to put wiat() methods inside loops, to check if the thing you are waiting for has really happened or not.
Again, this is not going to be on the exam. Except the part about putting wait inside a loop. You don't have to fully understand all the reason why it goes in a loop, but you do need to use a loop. The details of that are covered in the next section of the book.