面试题答案
一键面试设计思路
- 任务抽象:将任务定义为一个
trait
,每个具体任务实现该trait
。 - 优先级队列:使用
PriorityQueue
来存储任务,根据任务优先级进行排序。 - 线程池:创建一个线程池来执行任务,线程从优先级队列中获取任务并执行。
- 策略模式:可以通过实现不同的调度策略来决定如何从队列中获取任务,比如公平调度、优先调度高优先级任务等。
关键代码示例
use std::sync::{Arc, Mutex};
use std::thread;
use std::collections::BinaryHeap;
use crossbeam::thread::scope;
use priority_queue::PriorityQueue;
// 定义任务trait
trait Task {
fn execute(&self);
}
// 具体任务示例
struct MyTask {
id: u32,
}
impl Task for MyTask {
fn execute(&self) {
println!("Task {} is executing", self.id);
}
}
// 任务调度器
struct TaskScheduler {
tasks: Arc<Mutex<PriorityQueue<Box<dyn Task>, u32>>>,
}
impl TaskScheduler {
fn new() -> Self {
TaskScheduler {
tasks: Arc::new(Mutex::new(PriorityQueue::new())),
}
}
fn add_task(&self, task: Box<dyn Task>, priority: u32) {
self.tasks.lock().unwrap().push(task, priority);
}
fn run(&self, num_threads: usize) {
let tasks = self.tasks.clone();
scope(|s| {
for _ in 0..num_threads {
let tasks = tasks.clone();
s.spawn(|_| {
loop {
let mut tasks = tasks.lock().unwrap();
if let Some((task, _)) = tasks.pop() {
drop(tasks);
task.execute();
} else {
break;
}
}
});
}
}).unwrap();
}
}
使用示例
fn main() {
let scheduler = TaskScheduler::new();
scheduler.add_task(Box::new(MyTask { id: 1 }), 2);
scheduler.add_task(Box::new(MyTask { id: 2 }), 1);
scheduler.run(2);
}
在上述代码中:
- 定义了
Task
trait
,并给出MyTask
作为具体任务示例。 TaskScheduler
结构体包含一个PriorityQueue
来存储任务,add_task
方法用于添加任务,run
方法使用线程池来执行任务。- 在
main
函数中,创建调度器并添加任务,最后启动线程池执行任务。
请注意,代码中使用了crossbeam
库来创建线程池,priority_queue
库来实现优先级队列。如果环境中没有这些库,需要在Cargo.toml
文件中添加依赖:
[dependencies]
crossbeam = "0.8"
priority_queue = "1.3"