文章目录
前言
并发编程(Concurrent programming),指的是程序的不同部分相互独立的执行。而并行编程(parallel programming)代表程序不同部分于同时执行,这两个概念随着计算机越来越多的利用多处理器的优势时显得愈发重要。由于历史原因,在此类编程中一直是困难且容易出错的:Rust
希望能改变这一点。
在大部分现代操作系统中,已执行程序的代码在一个
进程(process)中运行,操作系统则负责管理多个进程。在程序内部,也可以拥有多个同时运行的独立部分。运行这些独立部分的功能被称为 线程(threads)。
一、创建线程
Rust创建线程是通过thread::spawn函数来创建的,我们只要通过这个函数,并且传入一个闭包即可创建出一个线程。
以两个线程同时输出数字为例,主线程输出1到5,子线程输出1到10。其代码如下所示
thread::spawn
函数内的闭包就是子线程的内容,以外的全都是主线程的内容。
thread::sleep
是一个线程延时的函数,需要传入Duration
,Duration
是个表示时间单位的,这里Duration::from_millis(1)
代表1毫秒,Rust支持更加精确的时间,你可以去看一下这个类,支持微秒
,纳秒
等。
thread::spawn(|| {
for i in 1..10 {
println!("数字是:{},来自spawn创建的线程", i);
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
println!("数字是:{},来自主线程线程", i);
thread::sleep(Duration::from_millis(1));
}
这样就创建好一个线程了,执行效果如下图
从图中可以看出主线程输出了从1到4的数字编号,因为到了5的时候已经执行完毕了,但是子线程却是执行到了5,并没有向后执行,这是因为主线程已经结束了,此时会把子线程也销毁,简而言之就是子线程的生存周期超出了主线程的生存周期,主线程提前结束。
原因:无法保证其执行顺序,主线程提前结束
为了解决这个,就需要接收这个线程的返回值,然后调用join方法来让主线程等待子线程执行完毕再结束运行。
thread::spawn返回一个JoinHandle,其有一个join方法,可以让主线程等待该线程完毕后再结束。
JoinHandle 是一个拥有所有权的值,当对其调用 join 方法时,它会等待其线程结束。join 放在循环之前可以实现先执行子线程【这种操作会变得同步,影响程序运行,因此需要方队地方,仔细斟酌】
处理以上的问题,因此对代码进行一下改动
let handle =thread::spawn(|| {
for i in 1..10 {
println!("数字是:{},来自spawn创建的线程", i);
thread::sleep(Duration::from_millis(1));
}
});