Escolar Documentos
Profissional Documentos
Cultura Documentos
Vida real: processos ocorrem simultaneamente (respiramos, pensamos, comemos, corao bate, andamos, o sangue circula...) Computadores:
Executam processos concorrentes; At agora s sabemos programar sequencialmente
Tarefa 3
Threads em Java
Suporte a multithreading faz parte da linguagem.
Todo programa executado em pelo menos uma thread.
class UmaUnicaThread { public static void main(String[] args) { // main() executado em um nica thread System.out.println(Thread.currentThread()); for (int i=0; i<30; i++) System.out.println("i == " + i); } }
Exemplo
Thread[main,5,main] i == 0 i == 1 i == 2 i == 3 i == 4 i == 5 i == 6 i == 10 i == 20 i == 11 i == 21 i == 12 i == 22 ... i == 29
Exemplo
class CountThread extends Thread O mtodo run( ) como { int from, to; se fosse um main( ), public CountThread(int from, int to) s que no esttico { this.from = from; this.to = to; } public void run() { for (int i=from; i<to; i++) System.out.println("i == " + i); } public static void main(String[] args) { // Dispara 5 threads, cada uma ir contar 10 vezes for (int i=0; i<5; i++) { CountThread t = new CountThread(i*10, (i+1)*10); t.start(); } } }
Exemplo
class CountThread extends Thread { int from, to; public CountThread(int from, int to) { this.from = from; this.to = to; } public void run() Iniciar uma thread ir criar { for (int i=from; i<to; i++) uma nova sequncia de System.out.println("i == " + i); controle e chamar o mtodo } run( ) da thread public static void main(String[] args) { // Dispara 5 threads, cada uma ir contar 10 vezes for (int i=0; i<5; i++) { CountThread t = new CountThread(i*10, (i+1)*10); t.start(); } } }
Exemplo
class CountThread extends Thread Thread uma { int from, to; classe em Java! public CountThread(int from, int to) { this.from = from; this.to = to; } public void run() { for (int i=from; i<to; i++) System.out.println("i == " + i); } public static void main(String[] args) { // Dispara 5 threads, cada uma ir contar 10 vezes for (int i=0; i<5; i++) { CountThread t = new CountThread(i*10, (i+1)*10); t.start(); } } }
Exemplo
main
0..9 10..19 20.29 30..39 40..49
Exemplo
1a. Execuo i == 0 i == 1 i == 2 i == 3 i == 4 i == 5 i == 6 i == 10 i == 20 i == 11 i == 21 i == 12 i == 22 ... 2a. Execuo i == 0 i == 1 i == 2 i == 3 i == 4 i == 10 i == 20 i == 11 i == 21 i == 31 i == 41 i == 5 i == 6 ...
Threads API
Thread()
Classe Thread possibilita a criao de um objeto executvel.
void run()
invocado pelo sistema de execuo da JVM. deve-se sobrescrever este mtodo (polimorfismo por sobreposio) para prover o cdigo a ser executado pela thread.
void start()
inicia a thread e provoca a chamada de run().
void stop()
pra a execuo da thread.
void suspend()
suspende a execuo da thread.
void resume()
retoma a execuo interrompida por um suspend().
Threads API
static void sleep(long millis) throws InterruptedException
pe a thread para dormir por um tempo em milisegundos.
void interrupt()
interrompe a thread em execuo.
Threads API
boolean isAlive()
testa se a thread est rodando.
void setPriority(int p)
define a prioridade de execuo da thread.
void yield()
indica ao gerenciador de threads que esta uma boa hora para rodar outras threads.
void join()
espera que uma thread termine sua execuo.
Estados
Estados
Uma thread finalizada:
atravs dos mtodos stop() ou destroy(). ao terminar a execuo do mtodo run().
algumas threads podem continuar rodando mesmo aps a finalizao do run().
Uma thread que no uma deamon chamada de thread de usurio. Em Java, um programa permanece em execuo enquanto ele possuir pelo menos uma thread no daemon executando. Quando s existem threads do tipo daemon rodando, o programa finalizado.
A interface Runnable adiciona o mtodo run() sem herdar nada de Thread. (Melhor!)
public interface Runnable { public void run(); }
Exemplo
/* Programa Java que dispara threads */ class CountThreadRun implements Runnable { int from, to; public CountThread(int from, int to) { this.from = from; this.to = to; } public void run() { for (int i=from; i<to; i++) System.out.println("i == " + i); } }
Exemplo
Para executar como uma thread:
// Cria uma instncia de Runnable Runnable r = new CountThreadRun(10,20); // Cria uma instncia de Thread Thread t = new Thread(r); // inicia a execuo da thread t.start();
Exemplo - MultiplaImpressao
/* Este programa cria uma classe chamada MultiplaImpressao*/ public class MultiplaImpressaoThread implements Runnable { Thread threadDaClasse; String string; int contador; int tempoDormindo; /* mtodo construtor da classe */ public MultiplaImpressaoThread (String s, int quantasVezes, int dormir) { contador = quantasVezes; string = s; tempoDormindo = dormir; threadDaClasse = new Thread (this); threadDaClasse.start(); } /*Fim do metodo construtor
Exemplo - MultiplaImpressao
public void run () {
while (contador > 0) { System.out.println (string); try { Thread.sleep (tempoDormindo); } catch (Exception e) { } } /*fim-while */
Exemplo (2)
class MeuApplet extends Applet implements Runnable { private Thread timer = null; public void init() { timer = new Thread(this); timer.start(); } ... public void run() { ... } }
Construtores
public public public public public Thread(); Thread(Runnable target); Thread(String name); Thread(Runnable target, String name); Thread(ThreadGroup group, Runnable target); public Thread(ThreadGroup group, String name); public Thread(ThreadGroup group, Runnable target, String name);
Escalonamento em Java
Mecanismo que determina como os threads executveis (runnable) iro utilizar tempo de CPU.
Preemptiva. filas de prioridades. no h diviso de tempo entre as filas (time sliced).
threads com menor prioridade podem ser executadas quando as de maior prioridade no estiverem rodando.
sleep(), yield(), stop()
Prioridade
Cada thread apresenta uma prioridade de execuo.
pode ser alterada com setPriority(int p) pode ser lida com getPriority()
Prioridade
Nem todo sistema operacional tem 10 nveis distintos de prioridade. O Windows, por exemplo, tem apenas 7. Assim, uma thread de prioridade n pode acabar tendo os mesmos privilgios (ou at menos) que outra de prioridade n-1, se ambas as prioridades forem mapeadas para um mesmo valor pela JVM.
Threads Egostas
Uma thread egosta aquela que quando toma conta da mquina, no quer sair nunca mais. Neste caso, s o SO pode retir-la da mquina. No boa prtica de programao fazer threads egostas. Soluo: usar os comandos sleep() e yield().
O mtodo sleep()
O mtodo sleep coloca o processo para dormir por um nmero de milissegundos definido pelo seu parmetro.
public void run() { for(;;) { try { sleep(1000); // Pause for 1 second } catch (InterruptedException e) { return; // caused by thread.interrupt() } System.out.println(Tick); } }
O mtodo sleep()
public void run() { for(;;) { try { sleep(1000); } catch (InterruptedException e) { return; } System.out.println(Tick); } }
Esta thread no necessariamente imprime a palavra Tick uma vez por segundo. Afinal, ela entra em estado idle e no necessariamente escalonada imediatamente aps acordar do seu sono. O tempo do sleep um limite inferior para o tempo entre impresses.
O mtodo interrupted() esttico enquanto que o isInterrupted() pertence ao objeto e no tem efeitos colaterais. O problema que esta thread uma thread egosta!!!!
Sendo bonzinho...
Uma maneira de uma thread ser gentil, usar o mtodo yield(). Usando este mtodo, ela sai do controle da mquina e diz para a JVM escalonar outra thread em seu lugar. O problema que se a thread boazinha a da mais alta prioridade, certas implementaes da JVM pode escalonla novamente. melhor chamar o mtodo sleep(). Assim garantimos que a thread atual no ser escalonada imediatamente...
Se voc fizer um loop infinito, voc pode fazer o sistema entrar em deadlock. while (!condition) {} Usar o comando yield evita o deadlock, mas muito ineficiente. while (!condition) {yield()}
A thread que pode afetar a condio de espera chama o mtodo notify() para acordar uma das threads que foi dormir. No necessariamente a thread que acorda aquela que queremos, O programador precisa se assegurar que para cada chamada de wait() existe uma chamada correspondente de notify()
Outra soluo
O mtodo notifyAll() habilita todas as threads que esto em estado de wait.
Uma delas ser escalonada e aproveitar da condio satisfeita. As outras, quando forem escalonadas, no tero a condio satisfeita e voltaro a dormir...
Agrupando Threads
Pode-se operar as threads como um grupo.
pode-se parar ou suspender todas as threads de uma s vez.
group.stop();
Agrupando Threads
Inclua uma thread em um grupo atravs do construtor da thread.
Thread t = new Thread(g,new ThreadClass(), "Esta thread");
Agrupando Threads
Para saber quantas threads em um grupo esto sendo executadas no momento, podemos usar o mtodo activeCount():
System.out.println("O nmero de threads "+ " que podem estar rodando "+ g.activeCount());
Gerenciando Threads
java.util.concurrent.Executors
A classe Executors estende a classe raiz Object. A classe Executors gerencia um grupo de threads.
Interface Executor Interface ExecutorService
SingleThreadExecutor usa uma thread para executar atividades seqencialmente. FixedThreadPool usa um grupo de threads de tamanho fixo para executar atividades. CachedThreadPool cria threads sob demanda.
Escalonando Threads
Um ScheduledExecutorService permite escalonar a execuo de atividades, definindo um atraso para incio da atividade e/ou um perodo de repetio entre execues. SingleThreadScheduledExecutor usa uma thread para todas as atividades escalonadas. ScheduledThreadPool cria um grupo de threads para executar as atividades.
Escalonando Threads
Sincronizao
Considere o seguinte cdigo:
public class Contador { private int conta = 0; public int incr() { int n = conta; conta = n + 1; return n; } }
Sincronizao
O que acontece caso tenhamos duas threads que iro executar o mesmo cdigo a seguir?
Ambas as threads esto acessando o mesmo objeto.
Situao 1
count 0 0 1 1 1 1 2 2
Situao 2
count 0 0 0 0 1 1 1 1
Monitores
public class Contador2 { private int conta = 0; public synchronized int incr() { int n = conta; conta = n + 1; No permite que este return n; mtodo seja executado } por mais de uma thread } ao mesmo tempo
Monitores
Tambm podemos usar monitores para partes de um mtodo.
synchronized(oObjeto) sentena; // Sincronizada em relao a oObjeto
Monitores
void metodo(UmaClasse obj) { synchronized(obj) { obj.variavel = 5; } }
Ningum poder usar este objeto enquanto estivermos executando estas operaes
Produtor Consumidor
O problema do produtor-consumidor um caso clssico de uma thread que deve esperar por uma condio a ser satisfeita por outras threads. No nosso caso abaixo, o Homer s pode comer biscoitos depois que a Marge os fizer!!!
Produtor e Consumidor
Consumidor synchronized (lock) { while (!resourceAvailable()) { lock.wait(); } consumeResource(); } Produtor produceResource(); synchronized (lock) { lock.notifyAll(); }
Quando o produtor executa, ele tira do estado de wait todos os objetos consumidores que esto esperando sobre o objeto lock
Objeto Lock
Thread Consumidor
Thread Produtor
A classe Homer
public class Homer implements Runnable { CookyJar jar; public Homer(CookyJar jar) { this.jar = jar; } public void eat() { jar.getCooky("Homer"); try { Thread.sleep((int)Math.random() * 1000); } catch (InterruptedException ie) {} } public void run() { for (int i = 1 ; i <= 10 ; i++) eat(); } }
A classe Marge
public class Marge implements Runnable { CookyJar jar; public Marge(CookyJar jar) { this.jar = jar; } public void bake(int cookyNumber) { jar.putCooky("Marge", cookyNumber); try { Thread.sleep((int)Math.random() * 500); } catch (InterruptedException ie) {} } public void run() { for (int i = 0 ; i < 10 ; i++) bake(i); } }
I/O completed
ready yield()
waiting
wait()
running
sleep()
sleeping
terminate dead