面试题答案
一键面试设计思路
- 通道创建:使用
std::sync::mpsc::channel
创建一个通道用于接收外部信号。这样主线程或其他线程可以通过通道发送信号给loop
循环所在的异步任务。 - 在
loop
中监听通道:在loop
内部使用select!
宏(来自futures
库),select!
宏可以同时等待多个Future
,这里我们等待通道接收消息的Future
以及异步任务的Future
。当通道接收到消息时,select!
会选择对应的分支执行,从而跳出loop
。 - 资源清理:对于异步任务中的资源,确保在
drop
实现中正确清理资源。如果资源需要异步清理,可以使用async_drop
等相关技术。
代码示例
use std::sync::mpsc::{channel, Receiver};
use futures::select;
use std::thread;
use std::time::Duration;
async fn async_task() {
// 模拟异步任务
println!("Async task started");
std::thread::sleep(Duration::from_secs(1));
println!("Async task finished");
}
fn main() {
let (tx, rx): (_, Receiver<bool>) = channel();
let handle = std::thread::spawn(move || {
tokio::runtime::Runtime::new().unwrap().block_on(async move {
loop {
select! {
_ = async_task() => {
// 异步任务完成,继续循环
},
_ = rx.recv().fuse() => {
// 接收到信号,跳出循环
println!("Received signal, exiting loop");
break;
}
}
}
});
});
// 模拟外部信号发送
thread::sleep(Duration::from_secs(3));
tx.send(true).unwrap();
handle.join().unwrap();
}
在上述代码中:
async_task
函数模拟了一个异步任务。main
函数中创建了一个通道(tx, rx)
,并在新线程中启动了一个异步任务。该异步任务在loop
中使用select!
宏等待async_task
完成或者从通道rx
接收到信号。- 主线程通过
tx.send(true)
模拟发送外部信号,接收到信号后,loop
会安全跳出,并且异步任务执行完成后资源得到正常清理。