Sobes.tech
Middle

Como funcionam os Executor em Java?

sobes.tech IA

Resposta da IA

Executor — é uma interface em Java que define um contrato para executar tarefas num pool de threads. Em vez de criar explicitamente threads para cada tarefa, envia as tarefas aos executores, que gerem a criação, uso e destruição dos threads.

As principais vantagens:

  • Gestão de threads: Fornece uma forma unificada de gerir o pool de threads, evitando a criação e sincronização manual de threads.
  • Eficiência: Reutiliza os threads existentes, reduzindo os custos associados à criação e destruição de threads.
  • Desempenho: Melhora o desempenho e a capacidade de resposta das aplicações através da execução assíncrona de tarefas.

Executor tem um método:

// Executa o comando dado em algum momento no futuro.
void execute(Runnable command);

Subtipos frequentemente utilizados:

  • ExecutorService: Estende Executor e fornece métodos adicionais para gerir o ciclo de vida do executor e obter resultados das tarefas (por exemplo, através de Future).
  • ScheduledExecutorService: Estende ExecutorService e permite executar tarefas com atraso ou de acordo com um horário.

A classe Executors fornece métodos de fábrica para criar diferentes tipos de executores:

// Cria um pool de threads com um número fixo de threads.
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

// Cria um pool de threads que pode ajustar dinamicamente o número de threads.
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

// Cria um pool de threads que pode executar tarefas agendadas.
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

Exemplo de uso:

// Objeto executor
ExecutorService executor = Executors.newFixedThreadPool(2);

// Tarefa para executar
Runnable task = new Runnable() {
    @Override
    public void run() {
        // Código da tarefa
        System.out.println("Tarefa a ser executada no thread: " + Thread.currentThread().getName());
    }
};

// Enviar tarefa ao executor
executor.execute(task);

// Encerrar o executor (necessário para libertar recursos)
executor.shutdown();

Ao chamar execute(), o executor pega a tarefa (Runnable) e atribui-a a um dos seus threads para execução. A gestão da distribuição de tarefas entre threads e o ciclo de vida é feita pelo executor.