创建future
await 关键字用于等待 Future 完成并获取其结果。
async fn async_function() -> i32 {
42 // 异步返回 42
}
#[tokio::main]
async fn main() {
let result = async_function().await;
println!("Result: {}", result);
}
同时等待多个 Future完成
use futures::join;
async fn future_one() -> i32 {
5
}
async fn future_two() -> String {
"hello".to_string()
}
#[tokio::main]
async fn main() {
let (result_one, result_two) = join!(future_one(), future_two());
println!("Result: {}, {}", result_one, result_two);
}
当一个 Future 完成后执行下一个操作:
use futures::future::FutureExt;
async fn future_one() -> i32 {
5
}
async fn future_two(v: i32) -> String {
format!("Value: {}", v)
}
#[tokio::main]
async fn main() {
let result = future_one()
.then(|v| future_two(v))
.await;
println!("Result: {}", result);
}
捕获错误并处理
use futures::future::TryFutureExt;
async fn future_with_error() -> Result<i32, &str> {
Err("An error occurred")
}
#[tokio::main]
async fn main() {
let result = future_with_error().unwrap_or_else(|e| {
println!("Error: {}", e);
-1 // 如果发生错误,返回默认值
}).await;
println!("Result: {}", result);
}
超时限制
#[tokio::test]
async fn test03() {
use tokio::time::{timeout, Duration};
async fn long_running_future() -> i32 {
tokio::time::sleep(Duration::from_secs(5)).await;
42
}
let result = timeout(Duration::from_secs(2), long_running_future()).await;
match result {
Ok(value) => println!("Completed with value: {}", value),
Err(_) => println!("Timeout occurred"),
}
}
多个Future的选择和竞赛
有时你希望同时启动多个 Future,并处理第一个完成的那个。
use tokio::time::{sleep, Duration};
use futures::select;
use futures::future::FutureExt;
#[tokio::main]
async fn main() {
let future1 = sleep(Duration::from_secs(2)).fuse();
let future2 = sleep(Duration::from_secs(1)).fuse();
futures::pin_mut!(future1, future2);
select! {
_ = future1 => println!("Future1 completed first"),
_ = future2 => println!("Future2 completed first"),
}
}
定时任务
#[tokio::test]
async fn test03() {
use tokio::time::{interval, Duration};
let mut interval = interval(Duration::from_secs(2)); // 每 2 秒 tick 一次
for _ in 0..5 {
interval.tick().await; // 等待下一个 tick
println!("Tick at {:?}", tokio::time::Instant::now());
}
println!("Done");
}
channel //多生产者单消费者通道,用于任务之间的消息传递。
use tokio::sync::mpsc;
use tokio::time::{sleep, Duration};
#[tokio::main]
async fn main() {
let (tx, mut rx) = mpsc::channel(100);
// 生产者任务
for i in 0..5 {
let tx = tx.clone();
tokio::spawn(async move {
tx.send(i).await.unwrap();
println!("Sent: {}", i);
});
}
// 消费者任务
tokio::spawn(async move {
while let Some(value) = rx.recv().await {
println!("Received: {}", value);
}
});
sleep(Duration::from_secs(1)).await; // 等待所有任务完成
}
设置线程池大小等参数,这个是从同步上下文中启动 Tokio 运行时
use tokio::runtime::Builder;
use std::time::Duration;
fn main() {
let rt = Builder::new_multi_thread()
.worker_threads(4) // 设置 4 个工作线程
.max_blocking_threads(32) // 设置最大阻塞线程数为 32
.thread_name("custom-thread") // 设置线程名称前缀为 "custom-thread"
.thread_stack_size(3 * 1024 * 1024) // 设置每个工作线程的栈大小为 3MB
.keep_alive(Some(Duration::from_secs(30))) // 设置线程保持存活时间为 30 秒
.on_thread_start(|| println!("Thread started"))// 线程启动时打印信息
.on_thread_stop(|| println!("Thread stopped")) // 线程停止时打印信息
.enable_all() // 启用所有 Tokio 特性
.build()
.unwrap();
rt.block_on(async {
// 在自定义运行时中运行异步代码
println!("Running on custom Tokio runtime");
});
}
tokio::sync::Mutex 用于在异步环境下保护共享数据,使得同一时间只有一个任务可以访问该数据。
use tokio::sync::Mutex;
use tokio::time::{sleep, Duration};
use std::sync::Arc;
#[tokio::main]
async fn main() {
let counter = Arc::new(Mutex::new(0)); // 共享计数器
let mut handles = vec![];
for _ in 0..5 {
let counter = Arc::clone(&counter);
let handle = tokio::spawn(async move {
for _ in 0..10 {
let mut num = counter.lock().await;
*num += 1;
println!("Incremented to: {}", *num);
sleep(Duration::from_millis(10)).await; // 模拟异步操作
}
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
println!("Final counter value: {}", *counter.lock().await);
}
tokio::sync::RwLock 提供了共享锁,允许多个读者并发访问,但同一时间只有一个写者访问。这在读多写少的场景下非常有用。
use tokio::sync::RwLock;
use tokio::time::{sleep, Duration};
use std::sync::Arc;
#[tokio::main]
async fn main() {
let shared_data = Arc::new(RwLock::new(String::from("initial data"))); // 共享数据
let mut handles = vec![];
// 写操作任务
for i in 0..5 {
let shared_data = Arc::clone(&shared_data);
let handle = tokio::spawn(async move {
let mut data = shared_data.write().await;
*data = format!("data from task {}", i);
println!("Write: {}", *data);
sleep(Duration::from_millis(500)).await; // 模拟异步操作
});
handles.push(handle);
}
// 读操作任务
for _ in 0..5 {
let shared_data = Arc::clone(&shared_data);
let handle = tokio::spawn(async move {
loop {
let data = shared_data.read().await;
println!("Read: {}", *data);
sleep(Duration::from_millis(100)).await; // 模拟异步操作
}
});
handles.push(handle);
}
// 等待所有任务完成
futures::future::join_all(handles).await;
println!("Final shared data: {}", *shared_data.read().await);
}
#[tokio::test]
async fn test04() -> io::Result<()> {
let mut file = File::create("foo.txt").await?;
file.write_all(b"Hello, world!").await?;
let mut file = File::open("foo.txt").await?;
let mut contents = vec![];
file.read_to_end(&mut contents).await?;
println!("File contents: {:?}", String::from_utf8(contents).unwrap());
Ok(())
}
任务间的同步屏障,等待所有任务到达后继续。
use tokio::sync::Barrier;
use tokio::time::{sleep, Duration};
use std::sync::Arc;
#[tokio::main]
async fn main() {
let barrier = Arc::new(Barrier::new(3));
let mut handles = vec![];
for i in 0..3 {
let c = barrier.clone();
let handle = tokio::spawn(async move {
println!("Task {} is waiting", i);
c.wait().await;
println!("Task {} is proceeding", i);
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
}
自定义的future
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>
- Pin<&mut Self>:一个被固定的位置指针,表示 Future 自身。通过 Pin 将 &mut Self 转换为 Pin<&mut Self> 来保证其固定位置。
- Context 提供了对当前异步任务的上下文信息,主要包括唤醒机制。它包含一个 Waker,用于在特定条件满足时唤醒任务继续执行。cx.waker().clone():获取 Waker 的克隆,确保可以在当前作用域外使用它。
impl Future for MyFuture {
type Output = &'static str;
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
if self.state == 0 {
self.state += 1;
println!("Polling MyFuture: Pending");
Poll::Pending
} else {
println!("Polling MyFuture: Ready");
Poll::Ready("Future is complete")
}
}
}
#[tokio::test]
async fn test01() {
let my_future = MyFuture { state: 0 };
// println!("Before awaiting MyFuture");
//
// // 模拟其他异步操作
// tokio::spawn(async {
// sleep(Duration::from_secs(1)).await;
// println!("Simulated async operation completed");
// });
let result = my_future.await;
println!("{}", result); // 输出: Future is complete
println!("After awaiting MyFuture");
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。