std::thread
创建线程
- thread::spawn() - 创建普通线程
- thread::scope() - 创建作用域线程(内部使用 s.spawn())
- Builder::spawn() - 使用构建器创建普通线程
- Builder::spawn_scoped() - 使用构建器创建作用域线程(在thread::scope()内部使用)
thread::spawn创建
thread::spawn(|| {
todo!();
})
使用
use std::thread;
use std::time::Duration;
fn main() {
let _ = thread::spawn(|| {
for i in 1..10 {
println!("thread::spawn: {}", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("main: {}", i);
thread::sleep(Duration::from_millis(1));
}
}
main: 1
thread::spawn: 1
main: 2
thread::spawn: 2
main: 3
thread::spawn: 3
main: 4
thread::spawn: 4
handle
join
thread::spawn返回一个JoinHandle,这个JoinHandle可以等待线程结束。
handle.join().unwrap();让当前线程等待handle的线程结束,并且获取线程返回值。
等待线程
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..5 {
println!("thread::spawn: {}", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..3 {
println!("main: {}", i);
thread::sleep(Duration::from_millis(1));
}
handle.join().unwrap();
}
thread::spawn: 1
main: 1
thread::spawn: 2
main: 2
thread::spawn: 3
thread::spawn: 4
获取返回值
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..5 {
println!("thread::spawn: {}", i);
thread::sleep(Duration::from_millis(1));
}
// 返回值
"aaaa"
});
for i in 1..3 {
println!("main: {}", i);
thread::sleep(Duration::from_millis(1));
}
let s = handle.join().unwrap();
println!("s: {}", s)
}
main: 1
thread::spawn: 1
main: 2
thread::spawn: 2
thread::spawn: 3
thread::spawn: 4
s: aaaa
获取线程信息
子线程内部获取线程信息:
thread::current()
use std::thread;
use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
thread::sleep(Duration::from_secs(2));
});
let t = handle.thread();
println!("t {:?}", t);
println!("t {:?}", t.id()); // 获取线程ID
println!("t {:?}", t.name()); // 获取线程名称
handle.join().unwrap();
}
t Thread { id: ThreadId(2), name: None, .. }
t ThreadId(2)
t None
丢弃handle
丢弃handle,子线程还是会执行。直到程序退出时,所有的子线程被强制停止
- 丢弃handle只是放弃控制,不等于终止线程
use std::thread;
use std::time::Duration;
fn main() {
{
let handle = thread::spawn(|| {
for i in 1..5 {
println!("spawned thread: {}", i);
thread::sleep(Duration::from_millis(1));
}
});
// 离开作用域handle被丢弃
}
// 睡的比子线程长
thread::sleep(Duration::from_secs(5));
}
spawned thread: 1
spawned thread: 2
spawned thread: 3
spawned thread: 4
thread::Builder创建
new创建
use std::thread;
fn main() {
let builder = thread::Builder::new();
let handler = builder.spawn(|| {
// 线程代码
}).unwrap();
handler.join().unwrap();
}
设置参数
use std::thread;
fn main() {
let builder = thread::Builder::new()
.name("my_thread".to_string())
.stack_size(1024 * 1024);
let handler = builder.spawn(|| {
// 线程代码
println!("{:?}", thread::current());
}).unwrap();
handler.join().unwrap();
}
Thread { id: ThreadId(2), name: Some("my_thread"), .. }
传递参数
使用
move关键字来获取参数所有权
- Copy类型: 实际复制
- Clone类型: 调用 clone
- 非Copy类型: 移动所有权
thread::spawn传参
use std::thread;
fn main() {
let value = 42;
let text = "Hello".to_string();
// 使用 move 关键字传递参数
let handle = thread::spawn(move || {
println!("Value: {}, Text: {}", value, text);
});
handle.join().unwrap();
}
Value: 42, Text: Hello
builder.spawn传参
use std::thread;
fn main() {
let value = 42;
let text = "Hello".to_string();
let handle = thread::Builder::new()
.name("parameter-thread".to_string())
.spawn(move || {
println!("Value: {}, Text: {}", value, text);
})
.unwrap();
handle.join().unwrap();
}
Value: 42, Text: Hello
在spawn调用函数
无参函数
thread::spawn
use std::thread;
fn test_thread() {
println!("Hello from a thread!");
}
fn main() {
let handle = thread::spawn(test_thread);
handle.join().unwrap();
}
thread::Builder
use std::thread;
fn test_thread() {
println!("Hello from a thread!");
}
fn main() {
let handle = thread::Builder::new()
.name("parameter-thread".to_string())
.spawn(test_thread)
.unwrap();
handle.join().unwrap();
}
有参函数
thread::spawn
use std::thread;
fn test_thread(value: i32, text: String) {
println!("Value: {}, Text: {}", value, text);
}
fn main() {
let value = 42;
let text = "Hello".to_string();
// 使用 move 关键字传递参数
let handle = thread::spawn(move || {
test_thread(value, text);
});
handle.join().unwrap();
}
thread::Builder
use std::thread;
fn test_thread(value: i32, text: String) {
println!("Value: {}, Text: {}", value, text);
}
fn main() {
let value = 42;
let text = "Hello World!".to_string();
let handle = thread::Builder::new()
.name("parameter-thread".to_string())
.spawn(move || {
test_thread(value, text);
})
.unwrap();
handle.join().unwrap();
}
作用域线程
使用
std::thread::scope创建的作用域线程,生命周期受特定作用域
- 优点
- 在作用域结束之前必须完成或终止,无需手动joinhandle
- 安全的访问数据,如需复制或克隆
参数访问
访问thread::scope外部参数
在
thread::scope之前的定义的参数都可以访问(借用)
可变不可变取决于外部定义
use std::thread;
use std::time::Duration;
fn main() {
let data = vec![1, 2, 3, 4, 5];
// 线程作用域
thread::scope(|s| {
// 在这个作用域内可以安全地借用外部数据
s.spawn(|| {
println!("线程作用域1: {:?}", data);
thread::sleep(Duration::from_secs(3));
println!("线程作用域1 end")
});
});
println!("主线程: {:?}", data);
}
线程作用域1: [1, 2, 3, 4, 5]
线程作用域1 end
主线程: [1, 2, 3, 4, 5]
访问thread::scope内部参数
use std::thread;
use std::time::Duration;
fn main() {
// 线程作用域
thread::scope(|s| {
// 在这个作用域内可以安全地借用外部数据
// 设置scope内部参数
let text = "hello world".to_string();
// 访问内部参数需要时move
s.spawn(move || {
println!("线程作用域1: {:?}", text);
thread::sleep(Duration::from_secs(3));
println!("线程作用域1 end")
});
});
}
线程作用域1: "hello world"
线程作用域1 end
返回值
use std::thread;
use std::time::Duration;
fn main() {
// 线程作用域
let s = thread::scope(|s| {
"aaa"
});
println!("{}", s);
}
aaa
并行处理
use std::thread;
use std::time::Duration;
fn main() {
// 线程作用域
thread::scope(|s| {
s.spawn(|| {
println!("s1 start");
thread::sleep(Duration::from_secs(3)); // 随眠3秒
println!("s1 end");
});
s.spawn(|| {
println!("s2 start");
thread::sleep(Duration::from_secs(1)); // 随眠1秒
println!("s2 end");
});
s.spawn(|| {
println!("s3 start");
thread::sleep(Duration::from_secs(2)); // 随眠2秒
println!("s3 end");
});
});
}
s1 start
s2 start
s3 start
s2 end
s3 end
s1 end
Builder的spawn_scoped
需要再
thread::scope创建
use std::thread;
fn main() {
let data = vec!["aa", "sss"];
thread::scope(|s| {
// spawn_scoped 需要满足 'scope 生命周期约束
thread::Builder::new()
.name("asd".to_string())
.spawn_scoped(s, || {
println!("Need move: {:?}", data);
}).unwrap();
});
}
Need move: ["aa", "sss"]
返回值
use std::thread;
use std::time::Duration;
fn main() {
let data = "aaa";
// 线程作用域
thread::scope(|s| {
let handle = thread::Builder::new()
.name("aaa".to_string())
.spawn_scoped(s, || {
thread::sleep(Duration::from_secs(1));
println!("hello world: {}", data);
"okok"
}).unwrap();
println!("handle: {}", handle.join().unwrap());
});
}
hello world: aaa
handle: okok
scope和spawn区别
| 特性 | 普通 thread::spawn |
thread::scope |
|---|---|---|
| 生命周期安全 | 不安全,可能导致悬垂指针 | 安全,编译时保证 |
| 外部数据访问 | 需要 move 或 Arc | 直接借用 |
| 线程管理 | 需要手动 join | 自动等待所有线程 |
| 内存安全 | 需要额外同步原语 | 编译时检查 |
| 错误传播 | 需要显式处理 | Panic 自动传播 |
| 性能开销 | 无额外开销 | 极小开销(几乎为零) |
| 适用场景 | 长生命周期线程 | 短生命周期并行任务 |

浙公网安备 33010602011771号