thread.join приостанавливает вызывающий поток до завершения thread. При нормальном завершении возвращается объект Thread, а при истечении переданного тайм-аута — nil, не false. Тайм-аут прекращает ожидание, но не отменяет работу потока. Необработанное исключение дочернего потока может быть повторно выброшено при join. Для результата блока используется thread.value.
Что делает Thread#join в Ruby?
Ожидание завершения потока, результат join, тайм-аут и получение значения через Thread#value.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
join — ожидание завершения другого потока. Он не запускает поток впервые: Thread.new уже создаёт и запускает работу, а join задаёт точку, после которой вызывающий код может рассчитывать на её завершение.
worker = Thread.new do
sleep 0.1
6 * 7
end
worker.join
p worker.value # 42
Сам join при нормальном завершении возвращает объект worker, а не число 42. value тоже ждёт завершения при необходимости и возвращает результат блока.
Можно ограничить время ожидания в секундах:
worker = Thread.new { sleep 0.1; :done }
if worker.join(0.01).nil?
puts "Пока не завершён"
end
worker.join # В примере явно дожидаемся оставшейся работы
При тайм-ауте результат — nil, а поток продолжает выполняться. Между возвратом по тайм-ауту и следующей строкой он уже может успеть завершиться, поэтому сообщение означает лишь результат данного ожидания. В приложении отдельно продумывают отмену или повторное ожидание.
Если работа завершилась необработанным исключением, оно распространяется в поток, который выполняет join или value. Обработчик ошибок должен учитывать этот сценарий. Ожидание всех задач не заменяет защиту общего изменяемого состояния во время их работы: для этого нужны подходящие средства синхронизации. Thread#join, Thread#value.