Yea, this question comes up often, mainly because there are a few mock questions that synchronize on the Thread object. You should do a bit of searching about it.
Anyway, the reason this is happening is due to implementation detail. The Thread class join() method is implementation via calls to check if the thread is alive and calling wait() on the Thread instance if it is not. When a thread terminates, part of the cleanup is to unset the alive flag and call notifyAll() on the thread object.
So... in your example, your thread object is terminating, and hence, sending a notification to all threads waiting on the Thread object.
O. Ziggy wrote:
In this example the thread does wait indefinitely. I dont understand the difference here and the previous example i gave.
In this second example, you are waiting on an instance that is not used by another part of the program -- hence, you are not being interfered with. In the first example, you were waiting on the same instance that the core library uses to implement the Thread.join() method.