Como matar um thread Java

Como matar um thread Java

1. Introdução

Neste breve artigo,we’ll cover stopping a Thread in Java – which is not that simple since the Thread.stop() method is deprecated.

Conforme explicado emthis update from Oracle,stop() pode fazer com que os objetos monitorados sejam corrompidos.

2. Usando uma bandeira

Vamos começar com uma classe que cria e inicia um tópico. Esta tarefa não terminará sozinha, então precisamos de alguma maneira de interromper esse thread.

Usaremos um sinalizador atômico para isso:

public class ControlSubThread implements Runnable {

    private Thread worker;
    private final AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    public ControlSubThread(int sleepInterval) {
        interval = sleepInterval;
    }

    public void start() {
        worker = new Thread(this);
        worker.start();
    }

    public void stop() {
        running.set(false);
    }

    public void run() {
        running.set(true);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.out.println(
                  "Thread was interrupted, Failed to complete operation");
            }
            // do something here
         }
    }
}

Em vez de ter um loopwhile avaliando uma constantetrue, estamos usando umAtomicBooleane agora podemos iniciar / parar a execução configurando-o paratrue/false.

Conforme explicado em nossointroduction to Atomic Variables, usar umAtomicBoolean evita conflitos na configuração e verificação da variável de diferentes threads.

3. Interrompendo aThread

O que acontece quandosleep() é definido para um intervalo longo, ou se estamos esperando por umlock que pode nunca ser liberado?

Corremos o risco de bloquear por um longo período ou nunca terminar de forma limpa.

Podemos criar ointerrupt() para essas situações, vamos adicionar alguns métodos e um novo sinalizador para a classe:

public class ControlSubThread implements Runnable {

    private Thread worker;
    private AtomicBoolean running = new AtomicBoolean(false);
    private int interval;

    // ...

    public void interrupt() {
        running.set(false);
        worker.interrupt();
    }

    boolean isRunning() {
        return running.get();
    }

    boolean isStopped() {
        return stopped.get();
    }

    public void run() {
        running.set(true);
        while (running.get()) {
            try {
                Thread.sleep(interval);
            } catch (InterruptedException e){
                Thread.currentThread().interrupt();
                System.out.println(
                  "Thread was interrupted, Failed to complete operation");
            }
            // do something
        }
    }
}

Adicionamos um métodointerrupt() que define nosso sinalizadorrunning como falso e chama o métodointerrupt() do thread de trabalho.

Se a thread estiver em espera quando for chamada,sleep() sairá comInterruptedException, como faria com qualquer outra chamada de bloqueio.

Isso retorna o thread para o loop, e ele sairá, poisrunning é falso.

4. Conclusão

Neste tutorial rápido, vimos como usar uma variável atômica, opcionalmente combinada com uma chamada ainterrupt(), para encerrar uma thread de forma limpa. Isso é definitivamente preferível a chamar o método obsoletostop() e correr o risco de travar para sempre e corromper a memória.

Como sempre, o código-fonte completo está disponívelover on GitHub.