pub fn spawn<F, T>(f: F) -> JoinHandle<T>where
F: FnOnce() -> T + Send + 'static,
T: Send + 'static,
Expand description
产生一个新线程,并为其返回一个 JoinHandle
。
连接句柄提供了一个 join
方法,可以用来连接新生成的线程。如果生成的线程发生 panics,那么 join
将返回一个 Err
,其中包含了提供给 panic!
的参数。
如果连接句柄被丢弃了,则新生成的线程将被隐式地 分离。 在这种情况下,新生成的线程可能不再被连接。 (程序有责任最终连接它创建的线程,或者将它们分离; 否则,将导致资源泄漏。)
此调用将使用 Builder
的默认参数创建一个线程,如果要指定栈大小或线程名称,请使用此 API。
正如您在 spawn
的签名中看到的那样,对于赋予 spawn
的闭包及其返回值都有两个约束,让我们对其进行解释:
-
'static
约束意味着闭包及其返回值必须具有整个程序执行的生命周期。这是因为线程可以比它们被创建时的生命周期更长。确实,如果线程以及它的返回值可以比它们的调用者活得更久,我们需要确保它们以后仍然有效,并且因为我们不能知道它什么时候返回,因此需要使它们直到程序结束时尽可能有效,因此是
'static
生命周期。 -
Send
约束是因为闭包需要通过值从产生它的线程传递到新线程。它的返回值将需要从新线程传递到它被join
的线程。 提醒一下,Send
标记 trait 表示从一个线程传递到另一个线程是安全的。Sync
表示将引用从一个线程传递到另一个线程是安全的。
Panics
如果操作系统无法创建线程,就会出现 panics。使用 Builder::spawn
从此类错误中恢复。
Examples
创建一个线程。
use std::thread;
let handler = thread::spawn(|| {
// 线程代码
});
handler.join().unwrap();
Run如模块文档中所述,线程通常是使用 channels
进行通信的,通常情况下是这样的。
此示例还展示了如何使用 move
,以便将值的所有权授予线程。
use std::thread;
use std::sync::mpsc::channel;
let (tx, rx) = channel();
let sender = thread::spawn(move || {
tx.send("Hello, thread".to_owned())
.expect("Unable to send on channel");
});
let receiver = thread::spawn(move || {
let value = rx.recv().expect("Unable to receive from channel");
println!("{value}");
});
sender.join().expect("The sender thread has panicked");
receiver.join().expect("The receiver thread has panicked");
Run一个线程也可以通过 JoinHandle
来返回一个值,您可以使用它进行异步计算 (不过 futures 可能更合适)。
use std::thread;
let computation = thread::spawn(|| {
// 一些昂贵的计算。
42
});
let result = computation.join().unwrap();
println!("{result}");
Run