Rust Concurrent Task Scheduler with Threads
Write a Rust program that develops a concurrent task schedule that executes tasks using multiple threads.
Sample Solution:
Rust Code:
use std::sync::{Arc, Mutex};
use std::thread;
// Define a type for tasks
type Task = Box<dyn FnOnce() + Send + 'static>;
// Define a structure for the task scheduler
struct TaskScheduler {
tasks: Arc<Mutex<Vec<Task>>>,
threads: Vec<thread::JoinHandle<()>>,
}
impl TaskScheduler {
// Create a new instance of the task scheduler
fn new() -> Self {
TaskScheduler {
tasks: Arc::new(Mutex::new(Vec::new())),
threads: Vec::new(),
}
}
// Add a task to the scheduler
fn add_task(&self, task: Task) {
self.tasks.lock().unwrap().push(task);
}
// Start the task scheduler with a specified number of threads
fn start(&mut self, num_threads: usize) {
for _ in 0..num_threads {
let tasks = Arc::clone(&self.tasks);
let handle = thread::spawn(move || {
loop {
// Lock the tasks vector
let task = tasks.lock().unwrap().pop();
// Execute the task if it exists
if let Some(task) = task {
task();
} else {
// If no task is available, break the loop
break;
}
}
});
self.threads.push(handle);
}
}
// Wait for all threads to finish executing
fn wait_all(&mut self) {
for handle in self.threads.drain(..) {
handle.join().unwrap();
}
}
}
fn main() {
// Create a new task scheduler
let mut scheduler = TaskScheduler::new();
// Add tasks to the scheduler
for i in 0..10 {
let task = Box::new(move || {
println!("Task {} executed by thread {:?}", i, thread::current().id());
});
scheduler.add_task(task);
}
// Start the task scheduler with 4 threads
scheduler.start(4);
// Wait for all threads to finish executing
scheduler.wait_all();
}
Output:
Task 9 executed by thread ThreadId(2) Task 8 executed by thread ThreadId(5) Task 5 executed by thread ThreadId(5) Task 4 executed by thread ThreadId(5) Task 3 executed by thread ThreadId(5) Task 2 executed by thread ThreadId(5) Task 1 executed by thread ThreadId(5) Task 0 executed by thread ThreadId(5) Task 7 executed by thread ThreadId(4) Task 6 executed by thread ThreadId(3)
Explanation:
In the exercise above,
- Define a Task type alias, representing a closure that takes no arguments and returns nothing (FnOnce() + Send + 'static). This type can be executed in parallel and sent between threads.
- Define a "TaskScheduler" structure to manage the execution of tasks. It contains a vector of tasks wrapped in a mutex to allow multiple threads to access it safely, as well as a vector of thread handles to keep track of spawned threads.
- The "TaskScheduler" has methods to add tasks (add_task), start executing tasks with a specified number of threads (start), and wait for all threads to finish executing (wait_all).
- In the "main()" function, we create a new "TaskScheduler" instance and add some tasks to it.
- We start the task scheduler with 4 threads using the "start()" method.
- Finally, we wait for all threads to finish executing using the "wait_all()" method
Rust Code Editor:
Previous: Rust Concurrent Web Server with Threads.
Next: Rust Parallel Merge Sort Algorithm with Threads.
What is the difficulty level of this exercise?
Test your Programming skills with w3resource's quiz.
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics