Как join объединяет потоки в Rust

Когда в Rust вы запускаете новый поток с помощью функции thread::spawn, эта функция не просто запускает поток — она ещё и возвращает специальный объект. Этот объект называется JoinHandle<T>. Его задача — дать вам возможность «связаться» с запущенным потоком и дождаться его завершения.

Проще говоря:

  1. Вы запускаете поток (thread::spawn).
  2. Вместо того чтобы сразу получить результат работы потока, вы получаете JoinHandle<T> — «ручку», с помощью которой можно управлять потоком.
  3. Позже вы можете использовать эту «ручку», чтобы дождаться окончания работы потока и получить от него результат.

Разберём термины

Пример:

  1. thread::spawn

Это функция в Rust, которая создаёт новый поток выполнения.

Представьте, что у вас есть главная «кухня», где вы готовите основное блюдо, и вы хотите, чтобы кто‑то параллельно приготовил салат. Вы отправляете помощника на эту задачу — это и есть запуск потока.

     use std::thread;

     let handle = thread::spawn(|| {
         // код, который будет выполняться в новом потоке
         42
     });
  1. JoinHandle<T>
    • JoinHandle можно перевести как «ручка для соединения». Это объект, который связывает вас с новым потоком.
    • <T> — это обозначение типа данных, которые поток вернёт после завершения работы. Например, если поток должен вернуть число, то T будет i32 (целое число).
    • Это как билет на поезд: вы отдаёте билет (запускаете поток), а потом по этому же билету можете узнать, когда поезд прибудет (дождаться окончания потока) и получить багаж (результат работы потока).
  2. Что значит «возвращает JoinHandle<T>»
    • Это значит, что после вызова thread::spawn вы не получаете сразу результат работы потока. Вместо этого вы получаете объект JoinHandle<T>, который хранит в себе информацию о запущенном потоке.
    • Этот объект — ваш «ключ» к управлению потоком.

Что можно сделать с JoinHandle<T>

Главный метод, который вы будете использовать с JoinHandle, — это join():

  • Метод join() «присоединяет» основной поток к дочернему, то есть заставляет основной поток ждать, пока дочерний поток не завершит свою работу.
  • Когда дочерний поток заканчивает работу, метод join() возвращает результат, который этот поток вычислил (тот самый T).
  • Если поток завершился с ошибкой (например, паникует), join() вернёт ошибку.

Пример:

let handle = thread::spawn(|| {
    // Поток делает какую‑то работу...
    10
});

// Основной поток продолжает работать, а дочерний выполняется параллельно.

// Когда нам нужен результат, мы вызываем join():
let result = handle.join().unwrap(); // result будет равен 10

Краткий итог

  • thread::spawn — функция, которая запускает новый поток.
  • «Возвращает JoinHandle<T>» — значит, что после запуска потока вы получаете специальный объект, который позволяет вам:
    • дождаться завершения потока;
    • получить результат его работы (или узнать об ошибке).
  • JoinHandle<T>.join() — метод, который:
    • останавливает выполнение текущего кода и ждёт, пока поток не закончится;
    • возвращает результат работы потока (T) или ошибку.

От admin

StackUP