一个进程一定有一个主线程,主线程之外创建出来的线程称为子线程
多线程编程,其实就是在主线程之外创建子线程,让子线程和主线程并发运行,完成各自的任务。
Rust语言支持多线程编程。
Rust语言标准库中的 std::thread 模块用于多线程编程。
std::thread 提供很很多方法用于创建线程、管理线程和结束线程。
一、创建线程
使用std::thread::spawn()方法创建一个线程。
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
参数 f 是一个闭包,是线程要执行的代码。
范例
use std::thread; // 导入线程模块 use std::time::Duration; // 导入时间模块 fn main() { //创建一个新线程 thread::spawn(|| { for i in 1..10 { println!("hi number {} from the spawned thread!", i); thread::sleep(Duration::from_millis(1)); } }); // 主线程要执行的代码 for i in 1..5 { println!("hi number {} from the main thread!", i); thread::sleep(Duration::from_millis(1)); } } 编译运行结果如下 hi number 1 from the main thread! hi number 1 from the spawned thread! hi number 2 from the main thread! hi number 2 from the spawned thread! hi number 3 from the main thread! hi number 3 from the spawned thread! hi number 4 from the spawned thread! hi number 4 from the main thread!
咦,执行结果好像出错了? 是吗?
当主线程执行结束,那么就会自动关闭创建出来的子线程。
上面的代码,我们调用 thread::sleep() 函数强制线程休眠一段时间,这就允许不同的线程交替执行。
虽然某个线程休眠时会自动让出cpu,但并不保证其它线程会执行。这取决于操作系统如何调度线程。
这个范例的输出结果是随机的,主线程一旦执行完成程序就会自动退出,不会继续等待子线程。这就是子线程的输出结果不全的原因。
二、让主线程等待子线程
默认情况下,主线程并不会等待子线程执行完毕。为了避免这种情况,我们可以让主线程等待子线程执行完毕然后再继续执行。
Rust标准库提供了 join() 方法用于把子线程加入主线程等待队列。
spawn<F, T>(f: F) -> JoinHandle<T>
范例
use std::thread; use std::time::Duration; fn main() { let handle = thread::spawn(|| { for i in 1..10 { println!("hi number {} from the spawned thread!", i); thread::sleep(Duration::from_millis(1)); } }); for i in 1..5 { println!("hi number {} from the main thread!", i); thread::sleep(Duration::from_millis(1)); } handle.join().unwrap(); } 编译运行结果如下 hi number 1 from the main thread! hi number 1 from the spawned thread! hi number 2 from the spawned thread! hi number 2 from the main thread! hi number 3 from the spawned thread! hi number 3 from the main thread! hi number 4 from the main thread! hi number 4 from the spawned thread! hi number 5 from the spawned thread! hi number 6 from the spawned thread! hi number 7 from the spawned thread! hi number 8 from the spawned thread! hi number 9 from the spawned thread!
从输出结果来看,主线程和子线程交替执行。
主线程等待子线程执行完毕是因为调用了 join() 方法。
三、move强制所有权迁移
这是一个经常遇到的情况:
实例
use std::thread; fn main() { let s = "hello"; let handle = thread::spawn(|| { println!("{}", s); }); handle.join().unwrap(); }
在子线程中尝试使用当前函数的资源,这一定是错误的!因为所有权机制禁止这种危险情况的产生,它将破坏所有权机制销毁资源的一定性。我们可以使用闭包的move关键字来处理:
实例
use std::thread; fn main() { let s = "hello"; let handle = thread::spawn(move || { println!("{}", s); }); handle.join().unwrap(); }
四、消息传递
使用通道传递消息,通道有两部分组成,一个发送者(transmitter)和一个接收者(receiver)。
std::sync::mpsc包含了消息传递的方法:
实例
use std::thread; use std::sync::mpsc; fn main() { let (tx, rx) = mpsc::channel(); thread::spawn(move || { let val = String::from("hi"); tx.send(val).unwrap(); }); let received = rx.recv().unwrap(); println!("Got: {}", received); } 运行结果: Got: hi
子线程获得了主线程的发送者tx,并调用了它的send方法发送了一个字符串,然后主线程就通过对应的接收者rx接收到了。
到此这篇关于Rust 多线程编程的实现的文章就介绍到这了,更多相关Rust 多线程内容请搜索好代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持好代码网!