Filas de Tarefas para C++: Implementação e Uso

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Filas de Tarefas para C++: da Teoria à Prática



A fila de tarefas (task queue) é um dos padrões-chave da programação multithread em C++. Ela permite distribuir o trabalho de forma eficiente entre as threads, evitando condições de corrida e consumo excessivo de recursos. Neste artigo, vamos abordar como criar e usar filas de tarefas em C++, com foco em desempenho e segurança.



Por que uma fila de tarefas?

Em aplicações modernas, surge frequentemente a necessidade de executar várias tarefas pequenas em paralelo. Criar threads diretamente para cada tarefa gera custos indiretos: a criação de uma thread consome tempo e memória. A fila de tarefas resolve esse problema através de um pool de threads (thread pool):

  • Reutilização de threads — as threads não são destruídas após a execução da tarefa, mas retornam ao pool.
  • Balanceamento de carga — as tarefas são distribuídas uniformemente.
  • Gerenciamento de recursos — limitação do número de threads simultâneas.


Implementação básica de uma fila de tarefas em C++

Vamos considerar uma fila de tarefas simples, mas thread-safe, usando std::queue e mutexes. Para isso, utilizamos a biblioteca padrão C++11 e superior.



#include <queue>#include <mutex>#include <condition_variable>#include <functional>#include <thread>#include <vector>

class TaskQueue {public: using Task = std::function<void()>;

explicit TaskQueue(size_t numThreads) : stop(false) { for (size_t i = 0; i < numThreads; ++i) { workers.emplace_back([this] { workerLoop(); }); } }

~TaskQueue() { { std::unique_lock<std::mutex> lock(mutex); stop = true; } condition.notify_all(); for (auto& worker : workers) { if (worker.joinable()) { worker.join(); } } }

void enqueue(Task task) { { std::unique_lock<std::mutex> lock(mutex); tasks.push(std::move(task)); } condition.notify_one(); }

private: void workerLoop() { while (true) { Task task; { std::unique_lock<std::mutex> lock(mutex); condition.wait(lock, [this] { return stop || !tasks.empty(); }); if (stop && tasks.empty()) { return; } task = std::move(tasks.front()); tasks.pop(); } task(); // Execução da tarefa } }

std::queue<Task> tasks; std::mutex mutex; std::condition_variable condition; bool stop; std::vector<std::thread> workers;};


Exemplo de uso

Agora, vamos mostrar como usar nossa classe TaskQueue para executar cálculos simples em paralelo:



#include <iostream>

int main() { TaskQueue tq(4); // Pool de 4 threads

for (int i = 0; i < 10; ++i) { tq.enqueue([i] { std::cout << "Tarefa " << i << " executada pela thread " << std::this_thread::get_id() << std::endl; }); }

// O destrutor de tq aguardará a conclusão de todas as tarefas return 0;}


Recursos avançados: fila com prioridades

Às vezes, é necessário processar tarefas na ordem de sua importância. Para isso, podemos usar std::priority_queue em vez de uma fila comum. Vamos adicionar suporte a prioridades:



#include <queue>#include <functional>

class PriorityTaskQueue {public: using Task = std::function<void()>;

struct PrioritizedTask { int priority; Task t

Recommendations