08-自定义线程
8.3.2 自定义线程
我们还可以通过设置其属性(例如名称或堆栈大小)来配置线程的API。为此,我们使用了thread模块中的Builder类型。这是一个简单的程序,它使用Builder类型创建了一个线程:
// customize_threads.rs
use std::thread::Builder;
fn main() {
let my_thread = Builder::new().name("Worker Thread".to_string())
.stack_size(1024 * 4);
let handle = my_thread.spawn(|| {
panic!("Oops!");
});
let child_status = handle.unwrap().join();
println!("Child status: {}", child_status);
}
在上述代码中,我们使用Builder::new方法,调用name和stack_size方法为线程分配名称和设置堆栈大小。然后我们在my_thread上调用spawn,它使用构造器实例生成线程。这一次在闭包中,我们的panic!宏带有“Oops”信息。以下是该程序的输出结果:
$ ./customize_threads
thread 'Worker Thread' panicked at 'Oops!', customize_threads.rs:9:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Child status: Err(Any)
可以看到该线程与我们给它提供的名称相同,即“Worker Thread”。此外,请注意Any类型返回的“Child status”消息。从线程中的panic!宏调用返回的值将作为Any类型返回,并且必须转换为特定的类型。这些就是构造线程的基础知识。
但是前面代码示例中生成的线程并没有做太多事情。我们使用并发是为了解决可以分解成多个子任务的问题。在通常情况下,这些子任务彼此独立,例如并行地对图像的每个像素应用过滤器。在其他情况下,线程中运行的子任务可能希望协调访问某些共享数据。
它们也可能用于执行计算,其最终结果取决于线程之间计算结果的汇总。例如,以多线程的方式从数据块中下载文件,然后将其传递给父级管理器线程。其他问题可能取决于共享状态,例如HTTP客户端向必须更新数据库的服务器发送POST请求。这里的数据库状态是所有线程共享的。
这些是并发比较常见的应用场景,并且线程能够在彼此之间,以及其父线程之间共享或传递数据是非常重要的。
让我们继续前进,看看如何在子线程中访问父线程中的现有数据。