创建多线程
use std::thread;
use std::time::Duration;
fn main() {
println!("{:?}, main begin", thread::current().id()); // 获取当前执行线程的线程号(Thread ID)
let handle1 = thread::spawn(|| {
for i in 1..4 {
println!("{:?}, child println num: {}", thread::current().id(), i);
thread::sleep(Duration::from_millis(1)) // 休眠1ms
}
}); // 线程可以有返回值
let handle2 = thread::spawn(|| {
for i in 1..=2 {
println!("{:?}, child println num: {}", thread::current().id(), i);
thread::sleep(Duration::from_millis(1))
}
});
handle1.join().unwrap(); // 等待子线程的结束才会往下执行
handle2.join().unwrap();
println!("{:?}, main end", thread::current().id()); // 获取当前执行线程的线程号(Thread ID)
}
// 输出:
// ThreadId(1), main begin
// ThreadId(2), child println num: 1
// ThreadId(3), child println num: 1
// ThreadId(2), child println num: 2
// ThreadId(3), child println num: 2
// ThreadId(2), child println num: 3
// ThreadId(1), main end
//
// 进程已结束,退出代码为 0
线程与move闭包
错误示例
fn main() {
let v = vec![1,2,3];
thread::spawn(||{
println!("v: {:?}",v)
});
drop(v);
}
执行报错
error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
--> src/main.rs:124:18
|
124 | thread::spawn(||{
| ^^ may outlive borrowed value `v`
125 | println!("v: {:?}",v)
| - `v` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src/main.rs:124:4
|
124 | / thread::spawn(||{
125 | | println!("v: {:?}",v)
126 | | });
| |_____^
help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword
|
124 | thread::spawn(move ||{
| ++++
原因分析:变量v在子线程中被使用时,子线程并不知道该变量的生命周期有多长,所以无法保证变量v在使用期间始终是有效的,为了安全起见,直接报错。
使用move
move
关键字通常用于闭包中,以明确将闭包环境中的变量所有权转移到闭包内
use std::thread;
use std::time::Duration;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
// // `v`的所有权被移动到了闭包内
println!("v: {:?}", v)
});
// 此处`v`的所有权已经转移,不能再使用`v`
// println!("v: {:?}",v); 如果启用这一行会导致编译错误
handle.join().unwrap();
}
创建线程池
Rust标准库(std
)本身不包含直接用于创建线程池的功能,为了使用线程池,推荐使用第三方库,如rayon
或threadpool
。
threadpool
threadpool
是一个轻量级线程池库,提供了基本的线程池功能
在Cargo.toml中添加依赖
[dependencies]
threadpool = "1.8.1"
示例:
use std::thread;
use std::time::Duration;
use threadpool::ThreadPool;
fn main() {
println!("{:?}-main thread begin", thread::current().id());
// 创建一个包含4个线程的线程池
let pool = ThreadPool::new(4);
// 向线程池提交任务
for i in 1..=8 {
pool.execute(move || {
println!("{:?}-Processing task {}", thread::current().id(), i);
thread::sleep(Duration::from_secs(1)); // 休眠1秒,模拟一些工作
println!("{:?}-Task {} completed", thread::current().id(), i);
});
}
// 等待所有任务完成
pool.join();
println!("{:?}-main thread end", thread::current().id());
}
// 输出:
// ThreadId(1)-main thread begin
// ThreadId(2)-Processing task 1
// ThreadId(3)-Processing task 2
// ThreadId(5)-Processing task 3
// ThreadId(4)-Processing task 4
// ThreadId(2)-Task 1 completed
// ThreadId(2)-Processing task 5
// ThreadId(3)-Task 2 completed
// ThreadId(3)-Processing task 6
// ThreadId(5)-Task 3 completed
// ThreadId(5)-Processing task 7
// ThreadId(4)-Task 4 completed
// ThreadId(4)-Processing task 8
// ThreadId(2)-Task 5 completed
// ThreadId(3)-Task 6 completed
// ThreadId(5)-Task 7 completed
// ThreadId(4)-Task 8 completed
// ThreadId(1)-main thread end
//
// 进程已结束,退出代码为 0
主线程的ID为1,其他子线程ID从2开始分配,线程池中有四个线程,即ID为2~5
rayon
rayon
是一个数据并行ism库,非常适合高性能并行处理
[dependencies]
rayon = "1.10.0"
示例:
fn main() {
println!("{:?}-main thread begin", thread::current().id());
let v: Vec<i32> = (0..=100).collect();
let sum: i32 = v.par_iter().sum(); // 并行化迭代和求和
println!("Sum of 0..101 is: {}", sum);
println!("{:?}-main thread end", thread::current().id());
}
// 输出:
// ThreadId(1)-main thread begin
// Sum of 0..101 is: 5050
// ThreadId(1)-main thread end