Короткий ответ
Поток создаётся через threading.Thread(target=функция, args=...), запускается методом start(), а join() блокирует текущий поток до завершения дочернего, что нужно для ожидания результата перед продолжением работы.
Как это работает подробнее
Thread.start() создаёт системный поток и запускает target-функцию параллельно основному потоку; без join() основная программа может продолжить выполнение, не дождавшись окончания работы дочернего потока.
Пример кода
example-252.py
import threading
result = {}
def worker(key, value):
result[key] = value * 2
t = threading.Thread(target=worker, args=("answer", 21))
t.start()
t.join()
print(result["answer"]) # 42 - гарантированно доступно после join()Что использовать на практике
- Практика.
join()используют, когда нужно гарантировать, что результат работы потока готов перед тем, как его читать, либо перед завершением программы, чтобы дочерние потоки успели корректно закончить работу.
Подводные камни
- Риски. Забывают
join()и обращаются к результату, который поток ещё не успел посчитать; вызываютjoin()с задачами, которые не завершаются, что приводит к зависанию основного потока без таймаута.