Rust多线程 - 线程建造者(Thread Builder)

普通创建线程

首先,先介绍一下普通创建线程的方法:使用 thread::spawn :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use std::{thread, time::Duration};

fn main() {
thread::spawn(|| {
for i in 1..10 {
println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});

for i in 1..5 {
println!("hi number {i} from the main thread!");
thread::sleep(Duration::from_millis(1));
}

println!("main thread end");
}

这里有几点值得注意:

  • 线程内部的代码使用闭包来执行
  • main 线程一旦结束,程序就立刻结束
  • thread::sleep 会让当前线程休眠指定的时间,随后其它线程会被调度运行

来看看输出:

1
2
3
4
5
6
7
8
9
10
hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
hi number 2 from the main thread!
hi number 3 from the spawned thread!
hi number 3 from the main thread!
hi number 4 from the spawned thread!
hi number 4 from the main thread!
hi number 5 from the spawned thread!
main thread end

如果多运行几次,可以发现每次输出会不太一样。因为虽然说线程往往是轮流执行的,但是这一点无法被保证!线程调度的方式往往取决于你使用的操作系统。总之,千万不要依赖线程的执行顺序

上面的代码在子线程没有输出完就结束了,因为主线程先结束,子线程也随之结束。我们可以调用join方法,让当前线程阻塞,直到子线程完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use std::{thread, time::Duration};

fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});

**handle.join().unwrap();**

for i in 1..5 {
println!("hi number {i} from the main thread!");
thread::sleep(Duration::from_millis(1));
}

println!("main thread end");
}

输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
hi number 3 from the spawned thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!
hi number 1 from the main thread!
hi number 2 from the main thread!
hi number 3 from the main thread!
hi number 4 from the main thread!
main thread end

Thread Builder创建线程

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use std::thread;

fn main() {
let handle = thread::Builder::new()
.name("Thread-1".into()) // 设置线程名称 如果panic将打印出 有助于定位问题
.stack_size(4 * 1024 * 1024) // 设置线程栈大小 默认2MB
.spawn(another_thread)
.unwrap();

handle.join().unwrap();
}

fn another_thread() {
print!("In thread: {}", thread::current().name().unwrap());
}

输出:

1
In thread: Thread-1

在Rust多线程编程中,thread::spawn是我们创建线程最直接的方式。但当默认配置无法满足需求:例如,我们需要在复杂的调试中识别特定线程,或者某个任务需要更大的栈空间时——spawn函数就显得力不从心了。这时候使用std::thread::Builder 进行线程的命名与栈大小的设置就很有必要了。

设置线程栈大小也可使用RUST_MIN_STACK环境变量,但在代码中使用Builder::stack_size 会覆盖其设置。主线程(main函数所在线程)的栈大小由操作系统或启动器控制。