Программа «Простой диспетчер задач»

Создание полнофункционального диспетчера задач — это достаточно сложная задача, и для такого проекта может потребоваться значительное количество кода и времени. Однако мы предоставим вам основу для простого диспетчера задач на разных языках программирования, который может выполнять базовые функции управления задачами.

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.

Обратите внимание, что этот подход имитирует выполнение задач в фоновом режиме, но он не предоставляет многозадачность на уровне потоков, как, например, другие языки программирования.

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...
Давайте поможем друг другу! Если вы нашли ошибку или хотите предложить лучшее решение, пожалуйста, напишите об этом в комментариях.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *