Bienvenidos sean a este post, hoy hablaremos sobre un metodo para los threads.
En el post anterior hablamos sobre crear un nuevo thread por medio de spawn y en el codigo que usamos de ejemplo el nuevo thread era eliminado cuando se terminaba el thread principal y como un poco de variacion notamos que realmente no siempre se respeta el orden correcto de ejecucion de los mismos, pero todo tiene solucion y aqui entra en accion join.
En realidad una cosa que no comentamos sobre spawn es que este devuelve un tipo denominado JoinHandle, y este tipo en conjunto con join nos permite esperar hasta que el thread haya terminado, por eso vamos a tomar el codigo del post anterior y lo modificaremos de la siguiente manera:
Nota: Si no lo tienen solamente generen un nuevo proyecto por medio de cargo y llamenlo engendro.
main.rs
use std::thread;
use std::time::Duration;
fn main()
{
let manejo = thread::spawn(|| {
for i in 1..10
{
println!("{} desde el nuevo thread", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5
{
println!("{} desde el thread ppal", i);
thread::sleep(Duration::from_millis(1));
}
manejo.join().unwrap();
}
Este codigo lo explicamos en el post anterior pero basicamente genera un nuevo thread sobre el thread principal, el cual tiene un bucle for para contar del 1 al 9, mostrarlo en pantalla y una pequeña demora de 1 ms, en el thread principal tenemos un bucle for donde contaremos de 1 a 4 y muy similar al otro bucle, como dijimos cuando se terminaba el thread principal este terminaba al nuevo, pero este codigo tiene dos diferencias con el anterior, la primera sera que el spawn que genera al nuevo thread lo almacenamos en una variable llamada manejo, y la segunda es que manejo tiene a join y unwrap, este metodo nos permitira manejar cualquier error o excepcion que pueda surgir, si lo compilamos y probamos veremos lo siguiente:
tinchicus@dbn001vrt:~/lenguajes/rust/engendro$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/engendro`
1 desde el thread ppal
1 desde el nuevo thread
2 desde el thread ppal
2 desde el nuevo thread
3 desde el thread ppal
3 desde el nuevo thread
4 desde el thread ppal
4 desde el nuevo thread
5 desde el nuevo thread
6 desde el nuevo thread
7 desde el nuevo thread
8 desde el nuevo thread
9 desde el nuevo thread
tinchicus@dbn001vrt:~/lenguajes/rust/engendro$
Observen como a diferencia del post anterior al momento de finalizar el thread principal no se interrumpio la ejecucion del thread nuevo sino que continuo con el mismo y cuando termino el thread nuevo recien finalizo la ejecucion del programa, vamos a hacer un simple cambio la siguiente linea:
manejo.join().unwrap();
La moveremos por detras de la variable que almacena la creacion del spawn, veamos como quedo nuestro nuevo codigo:
main.rs
use std::thread;
use std::time::Duration;
fn main()
{
let manejo = thread::spawn(|| {
for i in 1..10
{
println!("{} desde el nuevo thread", i);
thread::sleep(Duration::from_millis(1));
}
});
manejo.join().unwrap();
for i in 1..5
{
println!("{} desde el thread ppal", i);
thread::sleep(Duration::from_millis(1));
}
}
Que sucedera con esta modificacion? Compilemos y veamos como es su salida:
tinchicus@dbn001vrt:~/lenguajes/rust/engendro$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/engendro`
1 desde el nuevo thread
2 desde el nuevo thread
3 desde el nuevo thread
4 desde el nuevo thread
5 desde el nuevo thread
6 desde el nuevo thread
7 desde el nuevo thread
8 desde el nuevo thread
9 desde el nuevo thread
1 desde el thread ppal
2 desde el thread ppal
3 desde el thread ppal
4 desde el thread ppal
tinchicus@dbn001vrt:~/lenguajes/rust/engendro$
Pero que paso? Como dijimos al usar al join le estamos diciendo que hasta no terminar este thread no debemos ejecutar el otro (por mas que sea el principal) por lo tanto eliminara el intercalado anterior y solo priorizara el nuevo thread hasta que termine para iniciar con el otro, por lo tanto tengan esto en cuenta a la hora de usar el join.
En resumen, hoy hemos visto a join, como funciona, para que sirve, como lo podemos utilizar, un ejemplo de como nos ayuda con un codigo y como debemos tener especial atencion a la hora de usarlo, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
