Pesquisar este blog

quinta-feira, 25 de abril de 2013

Programação concorrente em Java (Threads)

Programacao concorrente:

Quando estamos usando o computador, muitas vezes estamos fazendo mais de uma coisa ao mesmo tempo, mas nem percebemos. Ouvimos musica, navegamos na internet e muitas vezes editamos documentos, tudo ao mesmo tempo.
Isso ja era possivel, mesmo na epoca dos processadores de um nucleo, coisa que so era possível devido as threads, ou programação concorrente.
Vamos comecar pelo o que e programação concorrente? 
Dizemos que um programa concorrente, e aquele que possui duas, ou mais partes do codigo, que podem ser executadas paralelamente.
Imagine que você esteja fazendo um programa e neste programa, você vai abrir um arquivo muito pesado. Leitura de arquivo e uma coisa bem lenta, e como você sabe que esta operação sera demorada, você quer mostrar uma barra de progresso, para o seu usuário.
Isto so e possivel devido a programação concorrente, que e realizada pelas threads. Cada thread é uma parte do programa que esta rodando, em java a maquina virtual é quem faz uma interface com o sistema operacional, que é quem realmente cuida de como e quando uma thread será executada.
Em java existem duas formas de conseguir rodar um código em paralelo:
  • Implementando a interface java.lang.Runnable
  • Extendendo a classe java.lang.Thread
A intereface Runnable define um método run, que e onde deveremos colocar o código que sera executado pela thread. A classe Thread implementa a interface Runnable.
Uma thread em java pode estar em um dos status mostrados a seguir:
  • NEW: thread criada mas ainda nao iniciada
  • RUNNABLE: quando a thread foi iniciada e pode ser executada pela maquina virtual
  • BLOCKED: quando a thread esta bloqueada esperando pela liberação de um lock para continuar a sua execução.
  • WAITING: Uma thread que esta esperando a execução de uma outra thread terminar para continuar a sua execução.
  • TIMED_WAITING: o mesmo que waiting, porem com um determinado tempo maximo de espera.
  • TERMINATED: uma thread que ja completou a sua execução.
Quando criamos uma thread ela esta no status new, para iniciarmos uma thread executamos o método start, com isso ela passa para o status de runnable.
Abaixo temos um exemplo de como criar uma thread:
public class ExemploConcorrencia implements Runnable{
     public void run{
            // Codigo a ser executado
    }
 Para executar o codigo acima faremos:
new ExemploConcorrencia().start();
 Na linha acima, construimos a thread e iniciamos a sua execução, a partir dai a maquina virtual vai executar o metodo run da thread.
O código colocado dentro do método run nem sempre sera executado por completo, do inicio ao fim. A máquina virtual java pode pausar a execução de uma Thread, para colocar outra Thread no lugar.
As threads tem um atributo chamado prioridade, este atributo influencia em como a máquina virtual vai escolher qual thread deve rodar, por exemplo uma thread com prioridade mínima só vai rodar, quando todas as threads com prioridade máxima estiverem pausadas por algum motivo.
O comportamento para prioridades das threads é diferente de plataforma para plataforma, por isso fique atento ao usar este atributo, pois ele pode ter um comportamento diferente de uma plataforma para outra. A máquina virtual é apenas uma interface para o verdadeiro controlador das threads, que é feito pelo sistema operacional.
Abaixo segue um exemplo de de um código usando Thread:
public class ExemploThread {
   // Mostra uma mensagem de acordo com o nome da thread atual   static void mensagemDaThread(String messagem) {
      String nomeDaThread =
      Thread.currentThread().getName();
      System.out.format("%s: %s%n",nomeDaThread,messagem);
   }
   private static class LoopDaMensagem implements Runnable {
      public void run() {
         String mensagens[] = {
           "Lpoo é a primeira matéria de java"            "Depois vem ALPOO",            "Finalmente quem sobrevive",            "Ai sim pode pegar o diploma"
         };
         try {
            for (int i = 0; i < mensagens.length; i++) {
            // Pause for 4 seconds
               Thread.sleep(4000);
             // Print a message
               mensagemDaThread(mensagens[i]);
            }
         } catch (InterruptedException e) {
            mensagemDaThread("Thread não finalizada!");         }
      }
   }
   public static void main(String args[])throws InterruptedException {
      mensagemDaThread("Iniciando a thread com o loop da mensagem");      long startTime = System.currentTimeMillis();
      Thread[] t = new Thread[5];
      for(int i=0;i<4;i++){
         t[i]= new Thread(new LoopDaMensagem()); 
         t[i].start();
      }
      mensagemDaThread("Esperando a thread terminar");      mensagemDaThread("Finalmente!");
   }
}

E o resultado de rodarmos ele em um ambiente Mac/Os:

main: Iniciando a thread com o loop da mensagem
main: Esperando a thread terminar
main: Finalmente!
main: Iniciando a thread com o loop da mensagem
main: Esperando a thread terminar
main: Finalmente!
Thread-1: Lpoo é a primeira matéria de java
Thread-2: Lpoo é a primeira matéria de java
Thread-4: Lpoo é a primeira matéria de java
Thread-3: Lpoo é a primeira matéria de java
Thread-1: Depois vem ALPOO
Thread-2: Depois vem ALPOO
Thread-4: Depois vem ALPOO
Thread-3: Depois vem ALPOO
Thread-1: Finalmente quem sobrevive
Thread-4: Finalmente quem sobrevive
Thread-3: Finalmente quem sobrevive
Thread-2: Finalmente quem sobrevive
Thread-1: Ai sim pode pegar o diploma
Thread-2: Ai sim pode pegar o diploma
Thread-3: Ai sim pode pegar o diploma
Thread-4: Ai sim pode pegar o diploma
Veja que a sequência de execução das Threads nem sempre é a mesma, e saiba que isso varia de sistema operacional para sistema operacional.

Nenhum comentário:

Postar um comentário