在 Rust 中,Stream
和 Future
是异步编程的重要概念,它们用于处理异步操作和数据流。
Future
Future
表示一个可能在将来完成的异步计算。它类似于其他编程语言中的 Promise
或 Task
。
定义
Future
是一个包含一个 poll
方法的 trait:
use std::task::{Context, Poll};
pub trait Future {
type Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}
poll
方法:检查Future
是否已经完成。如果完成,返回Poll::Ready(T)
,否则返回Poll::Pending
。Output
类型:表示Future
完成时的返回值类型。
示例
下面是一个简单的 Future
示例:
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
use tokio::time::sleep;
struct MyFuture {
when: Instant,
}
impl Future for MyFuture {
type Output = &'static str;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if Instant::now() >= self.when {
Poll::Ready("Hello, world!")
} else {
// 重新注册 waker,当时间到达时唤醒任务
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
#[tokio::main]
async fn main() {
let future = MyFuture {
when: Instant::now() + Duration::from_secs(2),
};
let result = future.await;
println!("{}", result);
}
在这个例子中,MyFuture
表示一个异步操作,它将在指定时间后完成并返回一个字符串。
wake_by_ref:通过引用唤醒任务,而不消耗 Waker,用于在条件不满足时重新注册任务,以便在未来某个时间点再次尝试。
Stream
Stream
表示一个异步的数据流,它可以产生一系列值。在某种程度上,它类似于 Iterator
,但用于异步上下文中。
定义
Stream
是一个包含一个 poll_next
方法的 trait:
use std::task::{Context, Poll};
pub trait Stream {
type Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
}
poll_next
方法:检查Stream
是否有新的数据。如果有,返回Poll::Ready(Some(T))
,如果流结束,返回Poll::Ready(None)
,否则返回Poll::Pending
。Item
类型:表示Stream
中产生的值的类型。
示例
下面是一个简单的 Stream
示例:
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
use tokio::time::sleep;
use futures::stream::Stream;
struct MyStream {
count: usize,
when: Instant,
}
impl Stream for MyStream {
type Item = usize;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if self.count >= 5 {
Poll::Ready(None)
} else if Instant::now() >= self.when {
let count = self.count;
self.get_mut().count += 1;
self.get_mut().when = Instant::now() + Duration::from_secs(1);
Poll::Ready(Some(count))
} else {
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
#[tokio::main]
async fn main() {
let stream = MyStream {
count: 0,
when: Instant::now(),
};
futures::pin_mut!(stream);
while let Some(item) = stream.next().await {
println!("Got: {}", item);
}
}
在这个例子中,MyStream
表示一个异步的数据流,它每秒钟产生一个值,最多产生五个值。
async
/await
Rust 提供了 async
/await
语法来简化 Future
和 Stream
的使用。async
函数返回一个实现了 Future
的对象,而 await
表达式则阻塞当前任务,直到 Future
完成。
示例
#[tokio::main]
async fn main() {
async fn say_hello() -> &'static str {
"Hello, world!"
}
let result = say_hello().await;
println!("{}", result);
}
这个例子展示了如何使用 async
函数和 await
表达式来处理异步操作。
总结
Future
:表示将来可能完成的异步计算,通过poll
方法检查是否完成。Stream
:表示异步的数据流,通过poll_next
方法生成一系列值。async
/await
:简化了Future
和Stream
的使用,使异步编程更加直观和易读。
Rust 的异步编程模型强大且灵活,适用于各种高性能和并发场景。通过理解 Future
和 Stream
以及 async
/await
语法,你可以编写高效的异步代码。