快速开始
cargo new rust-async-demo
创建项目, 在Cargo.toml
中添加 futures 依赖包- 在 src/main.rs 中输入如下代码, 运行查看效果
rust
use futures::executor::block_on;
async fn say_hi() {
println!("hi");
}
async fn say_hello() {
println!("hello");
}
async fn say_hey() {
println!("hey");
}
fn main() {
// 1.此时并没有输出(说明函数并没有直接执行)
let fut_hi = say_hi();
let fut_hello = say_hello();
let fut_hey = say_hey();
println!("###main###");
// 2.执行到此时才会输出(说明函数此时才真正执行)
block_on(fut_hello);
block_on(fut_hi);
block_on(fut_hey);
// 3. 异步函数执行顺序:
// 先输出 hello, 然后在输出 hi 和 hey
// 说明先执行的 say_hello 然后执行的 say_hi 和 say_hei
// 也就是说, 哪个异步函数的返回值先被传入 block 谁就先执行
}
rust
[package]
name = "rust-async-demo"
version = "0.1.0"
edition = "2021"
[dependencies]
futures = "0.3.31"
解析
异步函数的返回值
- 异步函数的语法返回的是一个实现了 std::future::Future 的实例对象
rust
// 接收一个实现 Future 特性的实例
fn my_block_on<T: Future>(f: T) {}
async fn say_hi() {
println!("hi");
}
fn main() {
my_block_on(say_hi());
// 这个代码并没有报错, 那么也就说明:
// say_hi 就是返回了一个 实现了 Future 特性的实例
// 否则代码应该报错, 类型不匹配才对
}
block_on 函数的作用
- 阻塞当前线程, 直到传入的 Feture 实例(或者说异步函数的返回值) 运行完成
rust
use futures::executor::block_on;
async fn say_hi() {
println!("hi");
}
async fn say_hello() {
println!("hello");
}
async fn say_hey() {
println!("hey");
}
fn main() {
let fut_hi = say_hi();
let fut_hello = say_hello();
let fut_hey = say_hey();
// 1. 输出: ###main###
println!("###main###");
// 2. 输出: hello
block_on(fut_hello);
// 3. 输出: hi
block_on(fut_hi);
// 4. 输出: hey
block_on(fut_hey);
}
WARNING
由代码的输出顺序可知, block_on
函数肯定会阻塞当前线程(主线程), 等待当前 block_on 中的 Future 实例执行完成, 然后(主线程)继续向下执行
上面这个代码既然会阻塞当前线程, 我直接同步执行不就完了吗? 那还要 Future 干嘛?
这时候就需要用到 await
关键字来代替 block_on
await 关键字
阻塞线程, 直至异步函数返回的 Future 执行完
rust
use std::thread::sleep;
use std::time::Duration;
use futures::executor::block_on;
async fn sit_down() {
sleep(Duration::from_secs(1));
println!("坐沙发");
}
async fn have_lunch() {
sleep(Duration::from_secs(1));
println!("吃午餐");
}
async fn watch_tv() {
sleep(Duration::from_secs(1));
println!("看电视");
}
async fn listen_music() {
sleep(Duration::from_secs(1));
println!("听音乐-来自电视")
}
async fn async_main() {
println!("async-main-start");
let fut1 = watch_tv();
let fut2 = listen_music();
// 2. await 关键字会等待 Future 执行完
println!("before: sit_down and have_lunch");
sit_down().await;
have_lunch().await;
println!("after: sit_down and have_lunch");
// 3. futures::join! 宏也会等待 Future 执行完
futures::join!(fut1, fut2);
println!("async-main-end");
}
fn main() {
println!("main-start");
// 1.阻塞线程, 等待 async_main 的返回值(Future实例)执行完
block_on(async_main());
println!("main-end");
}