Parando uma Thread em Java

Afinal, quando a execução de uma thread acaba? A execução acaba quando o método run() termina.

Ok, mas minha thread é um serviço que fica sempre em loop (ouvindo uma porta, por exemplo), ela não vai terminar nunca!

Uma hora ela vai precisar terminar, ou se seu programa for finalizado ou, caso seja um serviço do sistema, quando o sistema for desligado. Neste caso, o que eu mais vi sendo utilizado é uma variável boolean que é modificada pela classe “dona” que invocou a thread, parando a execução. O código seria nesse estilo:

public class SempreEmLoop implements Runnable {

  private volatile boolean stop = false;

  public void run() {

    while (!stop) {

      // ... faz o que tem que fazer

      try {
        Thread.sleep(100); // para nao deixar a cpu fervendo
      } catch (InterruptedException ex) {
        // nao ligo caso a thread seja interrompida durante o sleep
      }
    }

    // o laco acabou... alguem parou a execucao, liberar recursos
    finalizaFechandoArquivosSocketsEOutrasCoisas();
  }

  /**
   * Método que vai ser chamado para parar a thread
   */
  public void parar() {
    this.stop = true;
  }

}

Agora na classe que chama a Thread:

public class DonaDaThread() {

  private SempreEmLoop meuRunnableSempreEmLoop;

  public void iniciaMinhaThread() {
    meuRunnableSempreEmLoop = new SempreEmLoop();
    Thread minhaThread = new Thread(meuRunnableSempreEmLoop);
    minhaThread.start();
  }

  public void paraMinhaThread() {
    meuRunnableSempreEmLoop.parar();
  }
}

A classe DonaDaThread é que vai controlar a execução da thread que contém SempreEmLoop. Chamando o método donaDaThread.iniciaMinhaThread() vai inicializar uma thread que roda o método run() da classe SempreEmLoop. Chamando o método donaDaThread.paraMinhaThread() vai chamar o método parar() da SempreEmLoop que faz com que o laço while pare e libere os recursos que a thread estava utilizando.

Note que a variável boolean da SempreEmLoop é definida como volatile. O que eu li em outros lugares é que ela deve ser volatile para que o compilador não tente otimizar o laço while. Como a variável stop nunca é alterada dentro do laço, o compilador pode querer supor que stop é sempre false. Se colocar volatile o compilador não faz essa suposição e deixa stop do jeito que está, fazendo com que stop seja sempre verificada a cada iteração de while.

Existe também o método interrupt() na classe Thread, só que esse método interrompe a thread somente se ela estiver bloqueada (pelos métodos wait, join ou sleep).

Junho 5, 2008. Tags: . java.

No Comments Yet

Seja o primeiro a comentar!

Deixe um comentário

Você precisa fazer o login para publicar um comentário.

Trackback URL