Como interromper uma thread corretamente?

A interrupção de threads em Java deve ser feita de forma segura para evitar deadlocks e garantir que os recursos sejam liberados corretamente.

Como interromper uma thread corretamente?

Em Java, interromper uma thread corretamente é essencial para evitar problemas como deadlocks, vazamentos de recursos e comportamento inesperado.

1. O problema de interromper uma thread abruptamente

Antigamente, Java oferecia o método Thread.stop(), mas ele foi descontinuado pois podia deixar a aplicação em um estado inconsistente, interrompendo a thread imediatamente sem liberar recursos corretamente.

2. Como interromper uma thread de forma segura

A abordagem recomendada é usar flags de interrupção. A thread verifica periodicamente se foi interrompida e encerra sua execução de forma controlada.

Exemplo básico de interrupção com Thread.interrupt()

class MinhaThread extends Thread {
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("Thread em execução...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Thread foi interrompida!");
                break; // Sai do loop ao ser interrompida
            }
        }
        System.out.println("Thread finalizada corretamente.");
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        MinhaThread thread = new MinhaThread();
        thread.start();
        Thread.sleep(3000); // Espera 3 segundos
        thread.interrupt(); // Interrompe a thread
    }
}

Explicação:

  • isInterrupted() verifica se a thread foi interrompida.
  • Se sleep() for chamado, a interrupção lança InterruptedException.
  • O catch captura a exceção e finaliza a thread corretamente.

3. Interrompendo threads em ExecutorService

Se estiver usando ExecutorService, a interrupção funciona chamando shutdownNow():

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);

        Runnable tarefa = () -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("Executando tarefa...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("Tarefa interrompida!");
                    break;
                }
            }
        };

        executor.submit(tarefa);
        Thread.sleep(3000);
        executor.shutdownNow(); // Interrompe todas as threads
    }
}

Explicação:

  • shutdownNow() tenta interromper todas as threads do ExecutorService.
  • Cada thread verifica Thread.currentThread().isInterrupted().
  • Se estiver dormindo, uma exceção é lançada e a thread finaliza corretamente.

4. Erros comuns ao interromper threads

  • Não verificar isInterrupted(): A thread pode continuar rodando mesmo após a interrupção.
  • Ignorar InterruptedException: Se sleep(), wait() ou join() forem usados, é essencial tratar essa exceção corretamente.
  • Tentar reiniciar uma thread interrompida: Uma thread finalizada não pode ser reiniciada.

Conclusão

A interrupção correta de uma thread em Java deve ser controlada pelo próprio código da thread. A melhor abordagem é verificar periodicamente Thread.currentThread().isInterrupted() e tratar InterruptedException corretamente. Isso garante segurança, liberação adequada de recursos e melhor controle da concorrência.

Gerenciar a interrupção de threads corretamente é essencial para evitar problemas de desempenho e concorrência. Aplicações que executam tarefas demoradas, como processamento de arquivos ou requisições de rede, devem permitir a interrupção para evitar sobrecarga e melhorar a eficiência do sistema.

Algumas aplicações:

  • Encerramento seguro de processos em aplicações multithread
  • Evitar consumo excessivo de CPU ao interromper tarefas inúteis
  • Gerenciamento eficiente de recursos em aplicações concorrentes
  • Interrupção controlada de requisições longas em APIs

Dicas para quem está começando

  • Sempre verifique isInterrupted() dentro da thread
  • Trate InterruptedException corretamente ao usar sleep()
  • Evite Thread.stop() pois pode causar inconsistências
  • Use shutdownNow() para interromper threads no ExecutorService

Contribuições de Rodrigo Farias

Compartilhe este tutorial: Como interromper uma thread corretamente

Compartilhe este tutorial

Continue aprendendo:

O que são Semaphore e CountDownLatch

Semaphore e CountDownLatch são mecanismos de sincronização que ajudam a controlar o acesso de múltiplas threads a recursos compartilhados.

Tutorial anterior

Como usar CompletableFuture para programação assíncrona

O CompletableFuture é uma API poderosa do Java para executar tarefas assíncronas de forma eficiente e sem bloqueios.

Próximo tutorial