Реализация Thread.join использует ожидание, которое позволяет снять блокировку, поэтому не мешает другому потоку получить блокировку.
Вот пошаговое описание того, что происходит в этом примере:
Запуск потока MyThread в методе main приводит к тому, что новый поток выполняет метод выполнения MyThread.Основной поток спит целую секунду, давая новому потоку достаточно времени для запуска и получения блокировки объекта MyThread.
Новый поток может затем ввести метод ожидания и снять блокировку.В этот момент новый поток отключается, он не будет пытаться снова получить блокировку, пока он не проснется.Поток еще не возвращает из метода ожидания.
В этот момент основной поток выходит из спящего режима и вызывает завершение работы объекта MyThread.У него нет проблем с получением блокировки, потому что новый поток освободил его, как только начал ждать.Основной поток вызывает уведомления сейчас.При входе в метод соединения основной поток проверяет, что новый поток все еще жив, а затем ждет, сняв блокировку.
Уведомление происходит, когда основной поток снимает блокировку.Поскольку новый поток находился в состоянии ожидания, установленном для блокировки, в тот момент, когда основной поток вызвал notify, новый поток получает уведомление и активируется.Он может получить блокировку, выйти из метода ожидания и завершить выполнение метода run, наконец сняв блокировку.
Завершение нового потока приводит к тому, что все потоки, ожидающие его блокировки, получают уведомление.Это пробуждает основной поток, он может получить блокировку и проверить, что новый поток мертв, затем он выйдет из метода соединения и завершит выполнение.
/**
* Waits at most <code>millis</code> milliseconds for this thread to
* die. A timeout of <code>0</code> means to wait forever.
*
* @param millis the time to wait in milliseconds.
* @exception InterruptedException if any thread has interrupted
* the current thread. The <i>interrupted status</i> of the
* current thread is cleared when this exception is thrown.
*/
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}