w3resource

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

Go to:


PREV : Rust Concurrent Web Server with Threads.
NEXT : Rust Parallel Merge Sort Algorithm with Threads.

Rust Code Editor:

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.



Follow us on Facebook and Twitter for latest update.