面试题答案
一键面试设计思路
- 使用线程安全的队列:为了避免多个异步任务直接竞争控制台I/O,我们可以使用一个线程安全的队列来存储要输出的数据。每个异步任务将数据发送到这个队列,而不是直接输出到控制台。
- 单线程处理输出:启动一个单独的线程(或异步任务)从队列中取出数据并进行输出。这样可以确保控制台I/O操作是串行的,避免输出混乱。
- 数据标识:为不同类型的数据添加特定的前缀或颜色标识。在Rust中,可以使用
termcolor
库来实现颜色输出。
关键代码示例
use std::sync::{Arc, Mutex};
use std::thread;
use std::collections::VecDeque;
use std::sync::mpsc::{channel, Sender};
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
// 定义要输出的数据类型
enum OutputData {
Log(String),
Result(String),
}
fn main() {
let (sender, receiver) = channel();
let output_queue = Arc::new(Mutex::new(VecDeque::new()));
// 启动输出线程
let output_queue_clone = output_queue.clone();
thread::spawn(move || {
loop {
let data = receiver.recv().unwrap();
output_queue_clone.lock().unwrap().push_back(data);
flush_output(output_queue_clone.clone());
}
});
// 模拟多个异步任务
let sender_clone = sender.clone();
async_std::task::spawn(async move {
let log_data = OutputData::Log("This is a log message".to_string());
sender_clone.send(log_data).unwrap();
});
let sender_clone = sender.clone();
async_std::task::spawn(async move {
let result_data = OutputData::Result("The result is 42".to_string());
sender_clone.send(result_data).unwrap();
});
async_std::task::block_on(async {});
}
fn flush_output(output_queue: Arc<Mutex<VecDeque<OutputData>>>) {
let mut stdout = StandardStream::stdout(ColorChoice::Auto);
let mut queue = output_queue.lock().unwrap();
while let Some(data) = queue.pop_front() {
match data {
OutputData::Log(message) => {
let mut spec = ColorSpec::new();
spec.set_fg(Some(Color::Blue));
spec.set_bold(true);
write!(stdout.with(spec), "[LOG] {}", message).unwrap();
}
OutputData::Result(message) => {
let mut spec = ColorSpec::new();
spec.set_fg(Some(Color::Green));
spec.set_bold(true);
write!(stdout.with(spec), "[RESULT] {}", message).unwrap();
}
}
writeln!(stdout).unwrap();
}
}
在上述代码中:
OutputData
枚举定义了不同类型的数据。- 使用
std::sync::mpsc::channel
创建了一个通道,异步任务通过这个通道发送数据到输出线程。 output_queue
是一个线程安全的队列,用于存储要输出的数据。flush_output
函数从队列中取出数据,并根据数据类型添加不同的前缀和颜色进行输出。- 模拟了两个异步任务,向队列中发送不同类型的数据。