Function std::thread::spawn

1.0.0 · source ·
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