Filas de Tarefas em Java: dos mecanismos integrados aos frameworks modernos
Filas de Tarefas (Task Queues) são um padrão fundamental para construir aplicações Java escaláveis e tolerantes a falhas. Elas permitem separar a lógica de negócios do gerenciamento de threads, balancear a carga e processar tarefas de forma assíncrona. Neste artigo, analisaremos as principais implementações de filas de tarefas em Java, sua arquitetura, exemplos de código e cenários de uso.
1. Mecanismos integrados: ThreadPoolExecutor e BlockingQueue
A biblioteca padrão do Java (java.util.concurrent) oferece um conjunto poderoso de ferramentas para trabalhar com filas de tarefas. A base é a classe ThreadPoolExecutor, que gerencia um pool de threads e usa uma fila para armazenar tarefas em espera.
Exemplo básico:
import java.util.concurrent.*;
public class TaskQueueExample { public static void main(String[] args) { // Criando um pool de threads: corePoolSize=2, maxPoolSize=4, fila para 100 tarefas ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // corePoolSize 4, // maximumPoolSize 60, // keepAliveTime TimeUnit.SECONDS, new LinkedBlockingQueue<>(100) // fila de tarefas );
// Enviando tarefas for (int i = 0; i < 10; i++) { final int taskId = i; executor.submit(() -> { System.out.println("Tarefa " + taskId + " sendo executada pela thread " + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); }
// Encerramento correto executor.shutdown(); }}Tipos de filas para ThreadPoolExecutor:
LinkedBlockingQueue— fila ilimitada baseada em lista encadeada. Adequada para sistemas onde a quantidade de tarefas é desconhecida antecipadamente.ArrayBlockingQueue— fila limitada baseada em array. Permite controlar o número máximo de tarefas em espera.SynchronousQueue— fila sem capacidade: cadaput()aguarda umtake(). Usada para encaminhamento direto de tarefas às threads.PriorityBlockingQueue— fila com prioridade. As tarefas são ordenadas por um comparador definido.
2. Arquitetura Producer-Consumer baseada em filas
O padrão clássico Producer-Consumer é facilmente implementado com BlockingQueue. Os produtores (producers) colocam tarefas na fila, e os consumidores (consumers) as retiram para processamento.
Exemplo de implementação:
import java.util.concurrent.*;
public class ProducerConsumerExample { private static final BlockingQueue<String> queue = new LinkedBlockingQueue<>(5);
static class Producer implements Runnable { @Override public void run() { try { for (int i = 0; i < 10; i++) { String task = "Tarefa-" + i; queue.put(task); // bloqueia se a fila estiver cheia System.out.println("Produzida: " + task); Thread.sleep(100); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
static class Consumer implements Runnable { @Override public void run() { try { while (true) { String task = queue.take(); // bloqueia se a fila estiver vazia System.out.printl Também na biblioteca
Geração de PDF em Swift: criação de documentos para iOS e macOS
Trabalhando com S3 e armazenamentos em nuvem em C++: biblioteca aws-sdk-cpp