domingo, 2 de junho de 2013

Threads




Linha ou Encadeamento de execução (em inglês: Thread), é uma forma de um processo dividir a si mesmo em duas ou mais tarefas que podem ser executadas concorrentemente. O suporte à thread é fornecido pelo próprio sistema operacional (SO), no caso da linha de execução ao nível do núcleo, ou implementada através de uma biblioteca de uma determinada linguagem, no caso de uma User-Level Thread (ULT).
Uma thread permite, por exemplo, que o usuário de um programa utilize uma funcionalidade do ambiente enquanto outras linhas de execução realizam outros cálculos e operações.
Em hardwares equipados com uma única CPU, cada thread é processada de forma aparentemente simultânea, pois a mudança entre uma thread e outra é feita de forma tão rápida que para o utilizador isso está acontecendo paralelamente. Em hardwares com múltiplos CPUs ou multicores, as threads são realizadas realmente de forma simultânea.
As Threads são conhecidas como processos leves. Basicamente, esse atributo se deve ao menor tempo gasto em atividades de criação e escalonamento de threads, se comparadas aos processos. O compartilhamento de memória entre as threads maximiza o uso dos espaços de endereçamento e torna mais eficiente o uso destes dispositivos.

Exemplo
Um exemplo simples pode ser expressado através de um jogo onde o mesmo pode ser modelado com linhas de execução diferentes, sendo uma para desenho de imagem e outra para áudio; Neste caso, há um thread para tratar rotinas de desenho e outro thread para tratar áudio; No ponto de vista do usuário, a imagem é desenhada ao mesmo tempo em que o áudio é emitido pelos alto-falantes; Porém, para sistemas com uma única CPU, cada linha de execução é processada por vez.


Alguns Benefícios

1. Velocidade de Criação das Threads: as threads são mais fáceis de criar e destruir que os processos pois elas não tem quaisquer recursos associados a elas. Em alguns sistemas criar um thread pode ser cem vezes mais rápido do que criar um processo. No Solaris, criar um processo é aproximadamente 30 vezes mais lento do que criar um thread e a troca de contexto é aproximadamente 5 vezes mais lento.

2. Capacidade de Resposta: a utilização do multithreading pode permitir que um programa continue executando e respondendo ao usuário mesmo se parte dele está bloqueada ou executando uma tarefa demorada. Por exemplo, enquanto um navegador Web carrega uma figura ele permite a interação com o usuário.

3. Compartilhamento de Recursos: todos os recursos alocados e utilizados pelo processo aos quais pertencem são compartilhados pelos threads.

4. Economia: como os threads compartilham recursos dos processos aos quais pertencem, é mais econômico criar e realizar a troca de contexto de threads.

5. Utilização de Arquiteturas Multiprocessadas: é possível executar cada uma das threads criadas para um mesmo processo em paralelo (usando processadores diferentes). Isso aumenta bastante os benefícios do esquema multithreading.

6. Desempenho: obtido quando há grande quantidade de computação e E/S, os threads permitem que essas atividades se sobreponham e, logo, melhore o desempenho da aplicação.


Os estados e métodos básicos de um thread

New Thread
Inicialização do thread - feita através do construtor :

Thread().
   class MyThreadClass extends Thread{
                   ...
   }
   ...
   MyThreadClass myThread = new MyThreadClass();

Neste estado, nenhum recurso do sistema foi alocado para o thread ainda, assim, a partir daqui, tudo que você pode fazer é um start (), para ativar o thread, ou um stop(), para "matá-lo". A chamada de qualquer outro método não faz sentido e levantará a exceção IllegalThreadStateException.

 Runnable
Este é o estado em que o thread está pronto para rodar. O método start () requisita os recursos do sistema necessários para rodar o thread e chama o seu método run(). 



O método run() é a "alma" de um thread; é neste método que definimos que o thread vai executar.

   Thread myThread = new MyThreadClass();
        myThread.start();


Falamos em "Runnable", ao invés de "Running", porque o thread pode não estar realmente sendo executado. Imagine um computador com um único processador - seria impossível executar todos os threads "Runnable" ao mesmo tempo. O que ocorre é que a CPU deve ser escalonada entre os vários threads.

Quando um thread está "Running", ele está também "Runnable", e, as instruções do seu método run() é que estão sendo executadas pela CPU.

 Not Runnable
O estado "Not Runnable" significa que o thread está impedido de executar por alguma razão. Existem 4 maneiras através das quais um thread ir para o estado "Not Runnable":
o        Alguém manda-lhe a mensagem suspend().
o        Alguém manda-lhe a mensagem sleep().
o        O thread bloqueia, esperando por I/O.
o        O thread usa seu método wait() para esperar por uma variável de condição.
O exemplo abaixo coloca o applet myThread para dormir por 10 segundos...
   Thread myThread = new MyThreadClass();
        myThread.start();
        try {
             myThread.sleep(10000);
        } catch (InterruptedException e){
        }

Cada uma destas maneiras tem a sua forma específica de sair do estado "Not Runnable".
    • Se o thread foi suspenso, alguém precisa mandar-lhe a mensagem resume().
    • Se o thread foi posto para dormir, ele voltará a ser "Runnable" quando o número de milisegundos determinado passar.
    • Se o thread está bloqueado, esperando por I/O, a I/O precisa ser completada.
    • Se o thread está esperarando por uma variável de condição, o objeto que a "segura" precisa liberá-la, através de um notify() ou de um notifyAll()

 Dead
Um thread pode morrer de "causas naturais" (quando o seu método run()acaba normalmente) ou pode ser morto (AssAssINAdO :) pelo método stop()).
  
Thread myThread = new MyThreadClass();
        myThread.start();
   public void run() {
       int i = 0;
       while (i < 100) {
                   i++;
                   System.out.println("i = " + i);
       }
   }

Este thread vai morrer naturalmente

quando o loop do run() acabar.
  
Thread myThread = new MyThreadClass();
        myThread.start();
        try {
            Thread.currentThread().sleep(10000);
        } catch (InterruptedException e){
        }
        myThread.stop();


 O método yield()
Cede a CPU para outros threads.


Referências:
Wikipédia:

Centro de Computação USP:

UFPE:


Alunos: Guilherme Gasques, Aline Trombin, Georgya Sundfeld


Nenhum comentário:

Postar um comentário