Mostrando postagens com marcador Thread. Mostrar todas as postagens
Mostrando postagens com marcador Thread. Mostrar todas as postagens

quinta-feira, 8 de novembro de 2012

[Java] Thread X Runnable

Threads está entre os assuntos mais difíceis do exame SCJP/OCJP. O que podemos dizer sobre elas...

Basicamente, temos dois tipos de ambiente de execução (em se tratando de execução):

  • Execução de segmentação única. Onde as ações são executadas em fila, uma após a outra, necessariamente. 
  • Execução concorrente. Onde várias ações disputam a atenção dos recursos de forma independente.

Neste último caso, em Java, as ações concorrentes são threads concorrentes. É o que chamamos de threads de execução. Dispomos deste recurso quando precisamos que alguma ação ocorra independente de outra(s), quando não podemos ficar esperando uma ação terminar para continuar executando uma tarefa ou uma sequencia de tarefas.

Em Java, uma thread é uma instância de java.lang.Thread. As execuções de aplicações Java, ocorrem em pilhas de chamadas. Cada pilha de chamadas reside em uma única Thread. Logo, ao criar uma Thread, estamos criando uma nova pilha de chamadas, no mesmo processo.

Um processo é um conjunto de tarefas, que em um SO multitarefa, pode executá-las concorrencialmente. Exatamente, as Threads!

Como a VM tratará a execução das threads dependerá da implementação da VM. Isso mesmo! Não espere garantir que uma aplicação que crie várias instâncias de Thread tenha o mesmo comportamento em VMs diferentes. Então, se este for o caso, não se pode basear a implementação em uma VM específica, a menos que saiba que a aplicação só será executada naquela VM.

A classe java.lang.Thread expõe alguns métodos para gerenciar as threads:

  • start()
  • yield()
  • sleep()
  • run() - chame aqui o código que será executado pela thread.
Cria-se uma Thread de duas formas:
  • Estendendo java.lang.Thread, ou
  • implementando java.lang.Runnable.

Estender Thread pode parecer mais fácil, mas certamente não é a solução mais elegante!

Por que? Simplesmente pelo fato de que a herança, em OO, é um recurso para se especializar uma classe, para que se faça algo novo.

Então se você precisa apenas criar uma execução em uma thread separada, não há necessidade de especializar Thread. Lembre-se que ao estender Thread, não poderá estender mais nada! Neste caso, o mais lógico, seguindo princípios de OO, seria implementar Runnable.

Implementar Runnable vai permitir que sua classe estenda outra classe de negócio, além de dispor dos comportamentos de Thread (ou de Runnable. Thread implementa Runnable, sabia?!).

Dizemos que estender Thread é mais simples porque por este caminho, para criar uma nova thread, basta instanciar a subclasse de Thread que você criou:

public class minhaThread extends Thread{
  public void run(){
    //Chama a execucao da nova thread aqui.
  }
}

MinhaThread novaThread = new MinhaThread();

Implementando Runnable (recomendável na esmagadora maioria dos casos), ficaria assim:

//Cria a classe que implementa Runnable
public class MinhaRunnable implements Runnable{
  public void run(){
    //Chama a execucao da nova thread aqui.
  }
}

//Instancia MinhaRunnable
MinhaRunnable minhaRunnable = new MinhaRunnable();

//Cria uma instancia de Thread, passando sua Runnable para executar
Thread novaThread = new Thread(minhaRunnable);

A classe Runnable que passamos para a Thread, tecnicamente chama-se destino (target).

Até o momento, a thread foi criada, mas não foi executada, dizemos que o estado dela é new. Para executar a thread, basta chamar .start() e a thread passará de new para running:

//Para iniciar a thread
novaThread.start();

Sacou?

Espero ter te ajudado. Críticas, dúvidas e sugestões são bem vindas.

Forte abraço e até o próximo post.

Mauricio da Silva Marinho