Ответ
Метод Thread.join() заставляет текущий поток ожидать завершения потока, на котором он вызван. Вызывающий поток блокируется до тех пор, пока целевой поток не завершит выполнение.
Базовый пример:
Thread worker = new Thread(() -> {
System.out.println("Поток начал работу");
try { Thread.sleep(2000); } catch (InterruptedException e) {}
System.out.println("Поток завершил работу");
});
worker.start();
System.out.println("Основной поток запустил worker и ждёт...");
worker.join(); // Основной поток ждёт здесь завершения потока 'worker'
System.out.println("Основной поток продолжает работу после join.");
Варианты метода:
join()– ждёт бесконечно.join(long millis)– ждёт не более указанного времени в миллисекундах.join(long millis, int nanos)– с точностью до наносекунд.
Особенности:
- Если целевой поток уже завершён,
join()возвращается немедленно. - Метод может выбросить
InterruptedException, если ожидающий поток будет прерван. - Используется для синхронизации порядка выполнения потоков.
Ответ 18+ 🔞
А, ну ты глянь, какой у нас тут придурок Thread.join() объявился! Сидит, понимаешь, как будто в дверном проёме, и не пускает дальше, пока его братан-поток не отмучается. Представь: ты запустил какую-то хуйню в отдельном потоке, а самому надо, чтобы она точно доделалась, прежде чем ты свою продолжишь. Вот тут он и пригодится, этот затычка.
Смотри, как это выглядит в деле:
Thread worker = new Thread(() -> {
System.out.println("Поток начал работу");
try { Thread.sleep(2000); } catch (InterruptedException e) {}
System.out.println("Поток завершил работу");
});
worker.start();
System.out.println("Основной поток запустил worker и ждёт...");
worker.join(); // Вот эта строчка! Основной поток тут встал колом и ждёт, пока worker не сдохнет.
System.out.println("Основной поток продолжает работу после join.");
Выполнишь — и увидишь эту подлую синхронизацию: основной поток выведет своё «ждёт...» и, блядь, замрёт на две секунды, как вкопанный. Только когда worker отстреляется и напишет «завершил работу», основной поток охуеет от скуки и потащится дальше.
А вариантов у этого гвоздя в жопе аж три:
join()– будет ждать до победного конца, хоть до второго пришествия. Если поток уже кончился — ну, красава, проходи, не задерживай.join(long millis)– тут уже с таймером. «Я, сука, подожду ровно столько миллисекунд, а там — похуй, завершился он или нет, мне дальше надо».join(long millis, int nanos)– для совсем ебнутых перфекционистов, которым и наносекунды покоя не дают.
Важные нюансы, чтобы не обосраться:
- Если поток, на котором вызываешь
join(), уже труп (завершился), то метод сразу тебя отпустит, не задерживая. - Может выкинуть
InterruptedException— это если тебя, пока ты терпеливо ждёшь, вдруг прервут по-хамски. Придёшь в себя — обрабатывай. - В общем, инструмент для тех случаев, когда нужно выстроить потоки в очередь, чтобы они не неслись, как тараканы, кто куда попало. Синхронизация, ёпта, мать её.