MST

星途 面试题库

面试题:Rust中使用设计模式优化多线程任务调度

假设你正在开发一个多线程应用,有多个不同优先级的任务需要调度执行。请基于Rust并发编程,结合合适的设计模式(如策略模式、队列模式等),设计一个高效的任务调度系统。描述你的设计思路,并给出关键代码示例。
48.3万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 任务抽象:将任务定义为一个trait,每个具体任务实现该trait
  2. 优先级队列:使用PriorityQueue来存储任务,根据任务优先级进行排序。
  3. 线程池:创建一个线程池来执行任务,线程从优先级队列中获取任务并执行。
  4. 策略模式:可以通过实现不同的调度策略来决定如何从队列中获取任务,比如公平调度、优先调度高优先级任务等。

关键代码示例

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);
}

在上述代码中:

  1. 定义了Task trait,并给出MyTask作为具体任务示例。
  2. TaskScheduler结构体包含一个PriorityQueue来存储任务,add_task方法用于添加任务,run方法使用线程池来执行任务。
  3. main函数中,创建调度器并添加任务,最后启动线程池执行任务。

请注意,代码中使用了crossbeam库来创建线程池,priority_queue库来实现优先级队列。如果环境中没有这些库,需要在Cargo.toml文件中添加依赖:

[dependencies]
crossbeam = "0.8"
priority_queue = "1.3"