This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
If I use threadB.wait() in threadA and in threadB I do not call notify(), when the run() method of threadB finishes, then the threadA continues like I had call notify() in threadB...
This is an implementation detail -- which is of course, subject to change.
The join() method is implementated internally with the wait()/notifyAll(). A join() method call on the thread object does a wait() on the thread object. When the thread finishes, some of things that it does are, set the alive flag to indicate that it is not, and send a notifyAll() to all threads doing a join().
Obviously, you are not using the join() method, but you are waiting on the same notification object used by the join() method.