引言
在 Rust 异步编程中,Future 是一个核心概念。本文将通过实例,深入浅出地讲解 Future 的工作原理,帮助你更好地理解和使用 Rust 的异步编程。
Future 是什么?
Future 代表一个异步计算,它可能现在还没有值,但在未来的某个时刻会产生一个值。让我们通过一个简单的示例来理解:
// 一个简单的异步函数
async fn foo(n: u64) {
println!("start {n}"); // 打印开始
tokio::time::sleep(Duration::from_secs(1)).await; // 等待1秒
println!("end {n}"); // 打印结束
}
Future 的内部实现
实际上,每个异步函数都会返回一个 Future。我们可以将上面的异步函数转换为普通函数来理解其工作原理:
// Future 的具体实现
struct Foo {
n: u64,
started: bool, // 状态标记
sleep: Pin<Box<tokio::time::Sleep>>, // 睡眠 Future
}
impl Future for Foo {
type Output = ();
fn poll(mut self: Pin<&mut Self>, context: &mut Context) -> Poll<()> {
if !self.started {
println!("start {}", self.n);
self.started = true;
}
if self.sleep.as_mut().poll(context).is_pending() {
return Poll::Pending;
}
println!("end {}", self.n);
Poll::Ready(())
}
}
Future 的关键特点
状态机:Future 本质上是一个状态机,通过内部状态追踪执行进度 非阻塞:poll 方法要求快速返回,不能阻塞 可组合:多个 Future 可以组合执行,比如使用 join_all
实战示例:并发执行多个 Future
async fn main() {
// 创建多个异步任务
let futures = vec![
foo(1),
foo(2),
foo(3),
];
// 并发执行所有任务
join_all(futures).await;
}
总结
Future 是 Rust 异步编程的基础 异步函数会被编译器转换为实现了 Future trait 的状态机 Future 的 poll 方法负责推进异步计算的执行 使用 join_all 等工具可以方便地组合多个 Future
参考文章
Async Rust, Part One: Futures:https://jacko.io/async_futures.html
书籍推荐
各位 Rust 爱好者,今天为大家介绍一本《Programming Rust: Fast, Safe Systems Development》(第二版) 是由 Jim Blandy、Jason Orendorff 和 Leonora Tindall 合著的 Rust 编程指南。本书深入探讨了 Rust 语言在系统编程中的应用,着重介绍如何利用 Rust 的独特特性来平衡性能和安全性。书中涵盖了 Rust 的基础数据类型、所有权和借用概念、特征和泛型、并发编程、闭包、迭代器以及异步编程等核心内容。这本更新版基于 Rust 2021 版本,为系统程序员提供了全面而实用的 Rust 编程指导。