0Pricing
Learn Rust Coding · Lección

Unir hilos y recopilar resultados

Espere a los hilos y reúna la salida

Unir hilos y recopilar resultados es una lección gratuita de Learn Rust Coding en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Learn Rust Coding, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Learn Rust Coding incluye 4 lecciones en total.

¿Por qué unir hilos?

Crear un hilo inicia el trabajo, pero normalmente necesita su resultado o al menos comprobar que ha terminado. Unirlo es la forma de esperar.

En esta lección recopilará handles, hará join de ellos y reunirá los valores que producen en un resultado final.

join devuelve un Result

join devuelve un Result. Si la ejecución tiene éxito, contiene el valor devuelto por el closure; si el hilo produce un panic, contiene un Err.

Llamar a unwrap proporciona directamente el valor, pero propaga un panic si el hilo ha fallado.

use std::thread;

fn main() {
    let h = thread::spawn(|| 7 * 6);
    let value: i32 = h.join().unwrap();
    println!("answer = {}", value);
}

Recopilar primero los handles

Para ejecutar hilos en paralelo, créelos todos antes de unir cualquiera de ellos. Añada cada handle a un vector a medida que los cree.

Si hace join dentro del bucle de creación, cada hilo termina antes de que comience el siguiente y pierde el paralelismo.

use std::thread;

fn main() {
    let handles: Vec<_> = (0..4)
        .map(|i| thread::spawn(move || i * i))
        .collect();
    for h in handles {
        println!("{}", h.join().unwrap());
    }
}

Recopilar resultados en un Vec

Puede hacer join de cada handle y añadir los valores devueltos a un vector de resultados.

Aquí tanto el orden de creación como el de join van de cero a tres, por lo que el vector de resultados termina en un orden predecible.

use std::thread;

fn main() {
    let handles: Vec<_> = (1..=4)
        .map(|n| thread::spawn(move || n * 10))
        .collect();
    let results: Vec<i32> = handles
        .into_iter()
        .map(|h| h.join().unwrap())
        .collect();
    println!("{:?}", results);
}

Sumar resultados en paralelo

Una vez recopilados los resultados, puede reducirlos. Aquí cada hilo calcula un valor parcial y main los suma.

Este esquema de map y después reduce es un patrón paralelo habitual.

use std::thread;

fn main() {
    let handles: Vec<_> = (1..=5)
        .map(|n| thread::spawn(move || n * n))
        .collect();
    let total: i32 = handles
        .into_iter()
        .map(|h| h.join().unwrap())
        .sum();
    println!("total = {}", total);
}

Dividir el trabajo en fragmentos

Para datos más grandes, divídalos en fragmentos y entregue cada fragmento a su propio hilo. Cada hilo devuelve una suma parcial.

Clonar cada fragmento en un Vec propio permite que el hilo sea propietario de su parte de forma segura.

use std::thread;

fn main() {
    let data: Vec<i32> = (1..=10).collect();
    let handles: Vec<_> = data
        .chunks(5)
        .map(|c| { let c = c.to_vec(); thread::spawn(move || c.iter().sum::<i32>()) })
        .collect();
    let total: i32 = handles.into_iter().map(|h| h.join().unwrap()).sum();
    println!("{}", total);
}

Gestionar el panic de un hilo

Si un worker puede producir un panic, no use unwrap a ciegas. Compruebe el Result de join para gestionar la ruta de error.

Esto mantiene activo el hilo principal incluso cuando falla un worker.

use std::thread;

fn main() {
    let h = thread::spawn(|| {
        if true { panic!("failed"); }
        1
    });
    match h.join() {
        Ok(v) => println!("got {}", v),
        Err(_) => println!("thread panicked"),
    }
}

Recopilar datos en un Vec compartido

En lugar de devolver valores, los hilos pueden añadirlos a un Arc<Mutex<Vec>> compartido. En ese caso, el orden es no determinista.

Después de hacer join de todos los hilos, bloquee el vector una vez para leer todos los resultados recopilados.

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let out = Arc::new(Mutex::new(vec![]));
    let mut handles = vec![];
    for i in 0..3 {
        let o = Arc::clone(&out);
        handles.push(thread::spawn(move || o.lock().unwrap().push(i)));
    }
    for h in handles { h.join().unwrap(); }
    println!("{:?}", out.lock().unwrap());
}

Hilos con ámbito

thread::scope permite que los hilos tomen prestados datos locales sin move ni Arc. El ámbito garantiza que todos los hilos terminen antes de que la función devuelva el control.

Esto hace que las lecturas paralelas de datos de la pila sean sencillas y seguras.

use std::thread;

fn main() {
    let data = vec![1, 2, 3];
    thread::scope(|s| {
        s.spawn(|| println!("sum {}", data.iter().sum::<i32>()));
        s.spawn(|| println!("len {}", data.len()));
    });
}

Devolver resultados desde el ámbito

Los hilos con ámbito también devuelven valores a través de sus handles. Debe hacer join de ellos dentro del ámbito para recopilar los resultados.

Como el ámbito bloquea hasta que se completa la ejecución, los datos prestados siguen siendo válidos durante todo el proceso.

use std::thread;

fn main() {
    let nums = vec![4, 5, 6];
    let total = thread::scope(|s| {
        let h = s.spawn(|| nums.iter().sum::<i32>());
        h.join().unwrap()
    });
    println!("total = {}", total);
}

No olvide hacer join

Si descarta un JoinHandle sin hacer join, el hilo se separa. Sigue ejecutándose, pero pierde su resultado y cualquier forma de esperar a que termine.

El proceso también puede finalizar antes de que termine un hilo separado. Haga join cuando necesite el resultado o confirmar que ha terminado.

Comprobación rápida

Compruebe su comprensión de la unión de hilos y la recopilación de resultados.

Resumen

Ha aprendido que join devuelve un Result que contiene el valor de un hilo o un panic. Inicie primero todos los hilos y, después, use join para mantener la concurrencia.

Puede recopilar los resultados en un Vec, reducirlos o añadirlos a un Arc<Mutex<Vec>> compartido. Los hilos con ámbito toman prestados datos locales de forma segura, y al descartar un handle el hilo se separa.

Ahora dispone de las herramientas fundamentales para trabajar con hilos y estado compartido en Rust.

Preguntas frecuentes

¿La lección «Unir hilos y recopilar resultados» es gratis?

Sí — el texto completo de «Unir hilos y recopilar resultados» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Learn Rust Coding, actualiza a CoddyKit PRO. El curso de Learn Rust Coding incluye 4 lecciones en total.

¿Qué aprenderé en «Unir hilos y recopilar resultados»?

Espere a los hilos y reúna la salida Practicas Learn Rust Coding con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Learn Rust Coding?

No se requiere experiencia previa. Learn Rust Coding en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Unir hilos y recopilar resultados»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Learn Rust Coding?

Sí. Cada lección de Learn Rust Coding incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Crear hilos
  2. Mover datos a los hilos
  3. Compartir con Arc y Mutex
  4. Unir hilos y recopilar resultados
← Volver a Learn Rust Coding