线程基础
每个程序都以一个主线程开始启动。主线程可以生成一个新线程,该线程将成为其子线程,子线程可以进一步产生自己的线程。
Rust 中最简单的多线程大概就是使用 thread::spawn
:
use std::thread;
fn fibonacci(n: u32) -> u32 {
if n == 0 {
return 0;
} else if n == 1 {
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
fn main() {
thread::spawn(|| {
let f = fibonacci(30);
println!("Hello from a thread!. fibonacci(30) = {}", f);
});
println!("Hello, world!");
}
运行这段代码,会发现闭包内的函数结果并没有被输出:
Hello, world!
子线程是以分离状态创建的,程序执行到 println!
后就结束了,而相对耗时的子线程并没有结束。如果想要看到正确的结果,需要等待子线程。thread::spawn
返回一个 JoinHandle
类型的值,可以将它存放到变量中。这个类型相当于子线程的句柄,用于连接线程。如果忽略它,就没有办法等待线程。
fn main() {
let child = thread::spawn(|| {
let f = fibonacci(30);
println!("Hello from a thread!. fibonacci(30) = {}", f);
f
});
println!("Hello, world!");
let v = child.join().expect("Could not join child thread");
println!("value: {:?}", v);
}
join
返回一个 Result
,可以使用 expect
方法来获取返回值。这样主线程就会等待子线程完成,而不会先结束程序了,就可以看到我们想要的结果:
Hello, world!
Hello from a thread!. fibonacci(30) = 832040
value: 832040
自定义线程
还可以通过 thread
中的 Builder
设置线程的属性来配置线程的 API,例如名称或者堆栈的大小。如果有panic!
会输出对应的调试信息,就可以看到线程名称。
fn main() {
let my_thread = Builder::new()
.name("my_thread".to_string())
.stack_size(1024 * 4)
.spawn(move || {
let v = fibonacci(30);
println!("fibonacci(30) = {}", fibonacci(30));
v
});
println!("Hello, world!");
let v = my_thread.unwrap().join().expect