Создание полнофункционального диспетчера задач — это достаточно сложная задача, и для такого проекта может потребоваться значительное количество кода и времени. Однако мы предоставим вам основу для простого диспетчера задач на разных языках программирования, который может выполнять базовые функции управления задачами.
C++
#include <iostream> #include <vector> #include <functional> #include <thread> #include <mutex> #include <condition_variable> class TaskDispatcher { public: TaskDispatcher(int numThreads) : stop(false) { for (int i = 0; i < numThreads; ++i) { threads.emplace_back(std::bind(&TaskDispatcher::worker, this)); } } ~TaskDispatcher() { { std::unique_lock<std::mutex> lock(queueMutex); stop = true; } condition.notify_all(); for (std::thread &thread : threads) { thread.join(); } } void addTask(std::function<void()> task) { std::unique_lock<std::mutex> lock(queueMutex); taskQueue.push_back(task); condition.notify_one(); } private: void worker() { while (true) { std::function<void()> task; { std::unique_lock<std::mutex> lock(queueMutex); condition.wait(lock, [this] { return stop || !taskQueue.empty(); }); if (stop && taskQueue.empty()) { return; } task = taskQueue.front(); taskQueue.pop_front(); } task(); } } std::vector<std::thread> threads; std::list<std::function<void()>> taskQueue; std::mutex queueMutex; std::condition_variable condition; bool stop; }; int main() { TaskDispatcher dispatcher(4); // Создаем диспетчер с четырьмя рабочими потоками. // Добавляем задачи для выполнения. for (int i = 0; i < 10; ++i) { dispatcher.addTask([i] { std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Задача " << i << " выполнена." << std::endl; }); } // Добавьте задачи по вашему усмотрению. std::this_thread::sleep_for(std::chrono::seconds(5)); // Подождем некоторое время, чтобы дать потокам завершить задачи. return 0; }
Этот пример создает простой диспетчер задач с заданным количеством рабочих потоков и позволяет добавлять задачи для выполнения. Диспетчер будет выполнять эти задачи в фоновых потоках. Обратите внимание, что это простой пример и не включает в себя все возможности полноценного диспетчера задач.
C#
Пример простого диспетчера задач на C# с использованием Task и BlockingCollection:
using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; class TaskDispatcher { private BlockingCollection<Action> taskQueue = new BlockingCollection<Action>(); private int numWorkers; private Task[] workers; public TaskDispatcher(int numWorkers) { this.numWorkers = numWorkers; workers = new Task[numWorkers]; for (int i = 0; i < numWorkers; i++) { workers[i] = Task.Factory.StartNew(Worker); } } public void AddTask(Action task) { taskQueue.Add(task); } private void Worker() { foreach (var task in taskQueue.GetConsumingEnumerable()) { task(); } } public void Stop() { taskQueue.CompleteAdding(); Task.WaitAll(workers); } } class Program { static void Main() { TaskDispatcher dispatcher = new TaskDispatcher(4); // Создаем диспетчер с четырьмя рабочими потоками. // Добавляем задачи для выполнения. for (int i = 0; i < 10; i++) { int taskNumber = i; dispatcher.AddTask(() => { Thread.Sleep(1000); // Имитация выполнения задачи Console.WriteLine("Задача " + taskNumber + " выполнена."); }); } // Добавьте задачи по вашему усмотрению. Console.ReadLine(); dispatcher.Stop(); // Остановка диспетчера при завершении программы. } }
Этот код создает простой диспетчер задач, позволяет добавлять задачи для выполнения и автоматически управляет рабочими потоками. Обратите внимание, что это простой пример и не включает в себя все возможности полноценного диспетчера задач, но он демонстрирует основные принципы работы.
Python
Простой диспетчер задач на Python можно создать с использованием библиотеки multiprocessing. Пример такого диспетчера:
import multiprocessing import time def task_worker(task_id): print(f"Задача {task_id} выполняется") time.sleep(2) print(f"Задача {task_id} завершена") def main(): num_workers = 4 # Количество рабочих потоков task_ids = range(1, 11) # Идентификаторы задач pool = multiprocessing.Pool(processes=num_workers) pool.map(task_worker, task_ids) pool.close() pool.join() if __name__ == "__main__": main()
В этом примере мы используем библиотеку multiprocessing, чтобы создать пул процессов для выполнения задач. Вы можете настроить количество рабочих процессов (num_workers) в зависимости от ваших потребностей.
Просто добавьте задачи для выполнения в список task_ids и укажите функцию task_worker, которая будет выполняться в каждом рабочем процессе.
Обратите внимание, что этот пример предполагает, что задачи выполняются параллельно в нескольких процессах, что может быть полезно для многозадачных операций.
Java
Пример простого диспетчера задач на Java с использованием ExecutorService:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class TaskDispatcher { public static void main(String[] args) { int numWorkers = 4; // Количество рабочих потоков ExecutorService executor = Executors.newFixedThreadPool(numWorkers); for (int i = 1; i <= 10; i++) { final int taskId = i; executor.execute(() -> { System.out.println("Задача " + taskId + " выполняется"); try { Thread.sleep(2000); // Имитация выполнения задачи } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Задача " + taskId + " завершена"); }); } executor.shutdown(); try { executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } }
В этом примере мы используем ExecutorService для создания пула потоков, в котором выполняются задачи. Вы можете настроить количество рабочих потоков, указав newFixedThreadPool(numWorkers). Затем мы добавляем задачи в пул с помощью метода execute.
Обратите внимание, что задачи выполняются параллельно в нескольких потоках, и мы ожидаем завершения всех задач перед завершением программы.
Pascal
Пример простого диспетчера задач на Pascal, который использует многозадачность с помощью потоков:
program TaskDispatcher; {$APPTYPE CONSOLE} uses SysUtils, Classes, SyncObjs, Windows; type TTask = class(TThread) private FTaskID: Integer; public constructor Create(TaskID: Integer); procedure Execute; override; end; constructor TTask.Create(TaskID: Integer); begin inherited Create(False); FTaskID := TaskID; end; procedure TTask.Execute; begin WriteLn('Задача ', FTaskID, ' выполняется'); Sleep(2000); // Имитация выполнения задачи WriteLn('Задача ', FTaskID, ' завершена'); end; var TaskID: Integer; Tasks: array of TTask; ThreadHandles: array of THandle; begin SetLength(Tasks, 10); // Создаем 10 задач SetLength(ThreadHandles, Length(Tasks)); for TaskID := Low(Tasks) to High(Tasks) do Tasks[TaskID] := TTask.Create(TaskID); // Запускаем задачи for TaskID := Low(Tasks) to High(Tasks) do ThreadHandles[TaskID] := Tasks[TaskID].Handle; // Ожидаем завершения всех задач WaitForMultipleObjects(Length(ThreadHandles), @ThreadHandles[0], True, INFINITE); // Освобождаем ресурсы for TaskID := Low(Tasks) to High(Tasks) do Tasks[TaskID].Free; end.
В этом примере мы создаем класс TTask, который представляет задачу, и каждый экземпляр этого класса представляет одну задачу. Затем мы создаем 10 задач и запускаем их в отдельных потоках с использованием TThread. Задачи выполняются параллельно и завершаются после имитации выполнения задачи (в данном случае, ожидания 2 секунды).
Обратите внимание, что этот код работает только в среде Windows, так как он использует функцию WaitForMultipleObjects.
JavaScript
Пример простого диспетчера задач на JavaScript с использованием setTimeout:
class TaskDispatcher { constructor(numWorkers) { this.numWorkers = numWorkers; this.taskQueue = []; this.workers = []; for (let i = 0; i < this.numWorkers; i++) { this.workers[i] = this.createWorker(i); } } createWorker(workerID) { return { workerID, isBusy: false, }; } addTask(task) { this.taskQueue.push(task); this.dispatchTasks(); } dispatchTasks() { for (const worker of this.workers) { if (!worker.isBusy && this.taskQueue.length > 0) { const task = this.taskQueue.shift(); worker.isBusy = true; console.log(`Задача ${task} выполняется с помощью рабочего ${worker.workerID}`); setTimeout(() => { console.log(`Задача ${task} завершена`); worker.isBusy = false; this.dispatchTasks(); }, 2000); // Имитация выполнения задачи (2 секунды) } } } } const dispatcher = new TaskDispatcher(4); // Создаем диспетчер с четырьмя рабочими потоками. // Добавляем задачи для выполнения. for (let i = 1; i <= 10; i++) { dispatcher.addTask(i); } // Добавьте задачи по вашему усмотрению.
В этом примере мы создаем класс TaskDispatcher, который управляет рабочими потоками (в данном случае, это просто объекты, представляющие рабочих) и очередью задач. Когда задачи добавляются в очередь, диспетчер распределяет их между рабочими потоками. Каждая задача имитирует выполнение в течение 2 секунд с использованием setTimeout.
Обратите внимание, что этот код предоставляет базовую реализацию диспетчера задач на JavaScript и не использует многозадачность на уровне потоков, как в других языках. JavaScript использует асинхронное выполнение событий, и этот пример показывает, как можно имитировать выполнение задач в асинхронной среде.
PHP
PHP — это скриптовый язык программирования, и в отличие от некоторых других языков, он не предоставляет многозадачность на уровне потоков, как, например, Java или C++. Однако вы можете создать простой диспетчер задач, используя асинхронное выполнение с помощью функции shell_exec, чтобы выполнять задачи в фоне. Пример такого диспетчера:
class TaskDispatcher { private $numWorkers; public function __construct($numWorkers) { $this->numWorkers = $numWorkers; } public function addTask($task) { for ($i = 0; $i < $this->numWorkers; $i++) { $pid = shell_exec("php task_worker.php $task > /dev/null 2>&1 &"); if (!empty($pid)) { echo "Задача $task выполняется в фоне (PID: $pid)\n"; return; } } echo "Все рабочие заняты, задача $task не выполнена\n"; } } // Используем диспетчер $dispatcher = new TaskDispatcher(4); // Создаем диспетчер с четырьмя рабочими "процессами". // Добавляем задачи для выполнения for ($i = 1; $i <= 10; $i++) { $dispatcher->addTask($i); } // Добавьте задачи по вашему усмотрению.
В этом примере мы создаем класс TaskDispatcher, который использует функцию shell_exec, чтобы выполнять задачи в фоновом режиме с помощью командной строки. При этом каждая задача выполняется в собственном процессе. Вы можете настроить количество рабочих процессов, указав $numWorkers при создании объекта TaskDispatcher.
Обратите внимание, что этот подход имитирует выполнение задач в фоновом режиме, но он не предоставляет многозадачность на уровне потоков, как, например, другие языки программирования.