Для чего используется метод join() у потока (Thread) в Java?

«Для чего используется метод join() у потока (Thread) в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Метод Thread.join() заставляет текущий поток ожидать завершения выполнения потока, у которого он был вызван.

Принцип работы: Поток, вызвавший join() (например, main), переходит в состояние WAITING до тех пор, пока целевой поток не завершит свою работу (TERMINATED).

Пример использования:

Thread backgroundThread = new Thread(() -> {
    try {
        System.out.println("Фоновый поток: начало работы.");
        Thread.sleep(3000); // Имитация долгой задачи
        System.out.println("Фоновый поток: работа завершена.");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});

backgroundThread.start();
System.out.println("Main поток: запустил фоновый и ждет его.");

backgroundThread.join(); // Main поток блокируется здесь

System.out.println("Main поток: фоновый поток завершился, продолжаю.");

Вывод программы:

Main поток: запустил фоновый и ждет его.
Фоновый поток: начало работы.
Фоновый поток: работа завершена.
Main поток: фоновый поток завершился, продолжаю.

Важные особенности:

  • Перегруженные версии: join(long millis) и join(long millis, int nanos) — ожидание с таймаутом.
  • Прерывание: Метод join() может выбросить InterruptedException, если ожидающий поток будет прерван.
  • Немедленный возврат: Если целевой поток уже завершен или не был запущен, join() возвращает управление немедленно.

Типичный use case: Координация потоков, когда главный поток должен дождаться результатов работы одного или нескольких фоновых потоков перед продолжением.