Back-End

30 nov, 2012

How-To: Implementando Threads em Java

Publicidade

Este é um tópico que costuma ser evitado por muitos e adorado por poucos. Estamos falando de Threads em Java. Uma vez que se aprende o princípio básico, sempre veremos necessidades de utilização, seja para concorrência ou até mesmo para coisas mais simples, como mostrar uma barra de progresso.

Uma Thread é similar à um programa com início, sequência de execução e fim em qualquer momento de sua execução. Porém a Thread não é um programa, já que não pode ser executada sozinha. Ela deve ser executada dentro de uma aplicação, e esta aplicação possuirá vários pontos de execuções, cada um representando uma Thread.

Tema também muito comum em entrevistas são os questionamentos sobre as Threads.

Como implementar, por exemplo?

Existem duas formas para isso:

01. Estendendo a Classe java.lang.Thread;
02. Implementando a Interface java.lang.Runnable.

Mas aí você pergunta: “já que é tão bom e sempre vou querer usar, quando precisarei usar?”

Nós usamos thread se queremos que uma parte de nosso código seja executado em paralelo. Para isso, devemos colocar o código dentro do método run(), da classe Thread ou da Interface Runnable.

Na verdade, o método run() pertence à Interface Runnable, e como a Classe Thread implementa essa Interface, ela também possui esse método.

Outra pergunta comum: “Qual a melhor maneira de implementar uma Thread? Estendendo a Classe Thread ou Implementando a Interface Runnable?”

A resposta acaba sendo uma questão de conhecimento da Orientação a Objetos, e não de conhecer Thread. Lembram de um dos princípios da OO, que diz que devemos ter cuidado com Herança, pois ela nos limita? E também como no Java não temos Herança múltipla (esqueçam a simulação através de interfaces), se herdarmos a Classe Thread estamos gastando nossa chance e não poderemos herdar outra caso precisarmos.

E não acredito que seja uma verdade absoluta, então gostaria de ouvir contra-argumentações sobre isso nos comentários.

Outra razão para a utilização da Interface é que, de acordo com OO, só devemos estender uma classe quando iremos prover novas funcionalidades para esta. Como na maioria dos casos só queremos usar o método run(), não tem por que estendermos.

Uma thread não será executada até que o método start() seja chamado.

Quando chamamos o método start(), a JVM executa o método run() a partir de uma thread própria, diferente da que está chamando o processo.

Se tentarmos chamar uma thread diretamente pelo método run(), ela será executada na mesma thread que está chamando, e não na sua própria thread, não havendo concorrência alguma e não fazendo sentido sua utilização.

Já se chamarmos o método start() duas vezes seguidas no mesmo Objeto Thread, ocorrerá uma exceção:

thread.start();
thread.start();// Essa linha irá gerar uma IllegalThreadStateException

Vamos agora ao nosso exemplo prático, no qual faremos das duas formas já apresentadas:

//Extendendo a classe Thread
class TesteThread extends Thread{

             public void run(){
                         System.out.println("Estou sendo executado pela Thread de nome: " + Thread.currentThread().getName());
             }
 }

 //Implementando a Interface Runnable
 class TesteRunnable implements Runnable{

             public void run(){
                         System.out.println("Estou sendo executado pela Thread de nome: " + Thread.currentThread().getName());
             }
 }

         //iniciando a Thread
         Thread testeThread = new TesteThread();
         testeThread.setName("T1");
         Thread testeRunnable = new Thread(new TesteRunnable(),"T2");

         testeThread.start();
         testeRunnable.start();

Uma thread estará no estado “finalizada” quando a execução do método run() terminar e você não puder chamar o método start() novamente.

Caso tenham gostado, deixem nos comentários e providenciaremos mais!

Referências: