Você está na página 1de 5

Introduo

Threads e Concorrncia em
Java (Material de Apoio)
|

Professor: Lau Cheuk Lung


http://www.inf.ufsc.br/~lau.lung
|

INE-CTC-UFSC

A maioria dos programas so escritos de modo seqencial


com um ponto de incio (mtodo main()), uma seqncia de
execues e um ponto de trmino.
z Em qualquer dado instante existe apenas uma instruo
sendo executada.
O que so threads ?
um simples fluxo seqencial de execuo que percorre um
programa.
Multithreading: o programador especifica que os aplicativos
contm fluxos de execuo (threads), cada thread designando
uma parte de um programa que pode ser executado
simultaneamente com outras threads.

1
INE-CTC-UFSC

Programao concorrente
|

main()

Programao concorrente

Todo programa, sendo monothread ou multithread, inicia com


a execuo da thread principal.

Exemplo de um programa monothread


g()

g()

Exemplo de um programa multithread


main()

g()

g()

Mecanismos de sincronizao e prioridade podem ser usados


para controlar a ordem de execuo de threads
independentes e colaboradas.
INE-CTC-UFSC

INE-CTC-UFSC

Threads Java so implementadas pela classe Thread do


pacote java.lang:

Esta classe implementa um encapsulamento independente


de sistema, isto , a implementao real de threads
oferecida pelo sistema operacional.
z A classe Thread oferece uma interface unificada p
para
todos os sistemas.
Portanto, uma mesma implementao do Java Thread
pode fazer com que a aplicao proceda de forma
diferentes em cada sistema.
Ver a API Thread Java em java.lang.Thread
z

Threads em Java

Por que usar threads ?


z Permitir que um programa faa mais de uma coisa ao
mesmo tempo. Cada thread pode fazer coisas diferentes ao
mesmo tempo, por exemplo:
Uma thread baixando uma figura da rede e outra
renderizando uma imagem;
Uma gerenciando a edio de um texto e outra cuidando
da impresso de um outro documento em background;
Criao de vrias threads para processamento de uma
tarefa de forma paralela.
Quando no usar threads ?
z Quando um programa puramente seqencial.

Threads em Java
|

Criando uma nova Thread


z Para que uma thread possa executar um mtodo de uma
classe, a classe deve:
Herdar (extend) a classe Thread (o qual implementa a
classe Runnable em si), ou;
Implementar a interface Runnable.
Runnable

http://java.sun.com

INE-CTC-UFSC

INE-CTC-UFSC

Herdando a class Thread

Implementando a classe Runnable

class MinhaThread1 extends Thread {


public void run() {
System.out.println("Bom Dia !");
}
}
| O mtodo
d run() contm
o cdigo
di que a thread
h d executa.
class Teste1 {
public static void main(String Args[]) {
new MinhaThread1().start();
}
}
|

Para executar a thread necessrio instanciar a classe


MinhaThread e invocar o mtodo start().
INE-CTC-UFSC

class MinhaThread2 implements Runnable {


public void run() {
System.out.println("Bom Dia !");
}
}
| Desta
D
fforma, a classe
l
MinhaThread pode
d h
herdar
d uma outra
classe.
class Teste2 {
public static void main(String Args[]) {
new Thread(new MinhaThread2()).start();
}
}
7

INE-CTC-UFSC

Execuo paralela de threads

Execuo paralela de threads


|

class ImprimirThread_1 implements Runnable {


String str;
public ImprimirThread_1(String str) {
this.str = str;
}
public void run() {
for(;;)
System.out.print(str);
}
}
class TesteConcorrente {
public static void main(String Args[]) {
new Thread(new ImprimirThread_1("A")).start();
new Thread(new ImprimirThread_1("B")).start();
}
}

Mtodo yield(), cede o processamento para outra thread.

class ImprimirThread_2 implements Runnable {


String str;
public ImprimirThread_2(String str) {
this.str = str;
}
public void run() {
for( ) {
for(;;)
System.out.print(str);
Thread.currentThread().yield();
}
}
}
class TesteConcorrente2 {
public static void main(String Args[]) {
new Thread(new ImprimirThread_2("A")).start();
new Thread(new ImprimirThread_2("B")).start();
}
}
9

INE-CTC-UFSC

Thread: diagrama de estado

10

INE-CTC-UFSC

Thread: diagrama de estado


Nova thread

new thread

runnable

non runnable

Pronta

Em execuo

running

Esperando

dead

INE-CTC-UFSC

11

Adormecida

Morta

INE-CTC-UFSC

Bloqueada

12

Prioridade de thread
|

Prioridade de thread

Cada thread possui uma prioridade de execuo que vai de


Thread. MIN_PRIORITY (igual a 1) a Thread.MAX_
PRIORITY (igual a 10).
Importante: uma thread herda a prioridade da thread que a
criou.
O algoritmo de escalonamento sempre deixa a thread
(runnable) de maior prioridade executar.
z A thread de maior prioridade preempta as outras threads
de menor prioridade.
z Se todas as threads tiverem a mesma prioridade, a CPU
alocada para todos, um de cada vez, em modo round-robin.
getPriority(): obtm a prioridade corrente da thread;
setPriority(): define uma nova prioridade.
z

INE-CTC-UFSC

13

class BaixaPrioridade extends Thread {


public void run() {
setPriority(Thread.MIN_PRIORITY);
for(;;) {
System.out.println("Thread de baixa prioridade
executando -> 1");
}
}
}
class AltaPrioridade extends Thread {
public void run() {
setPriority(Thread.MAX_PRIORITY);
for(;;) {
for(int i=0; i<5; i++)
System.out.println("Thread de alta prioridade
executando -> 10");
try {
sleep(100);
} catch(InterruptedException e) {
System.exit(0);
}
}
}
}

InterruptedException lana exceo se a thread interrompida pelo mtodo interrupt();


INE-CTC-UFSC

Prioridade de thread

Grupo de Threads

class Lanador {
public static void main(String args[]) {
AltaPrioridade a = new AltaPrioridade();
BaixaPrioridade b = new BaixaPrioridade();
System.out.println("Iniciando threads...");
b.start();
a.start();
// deixa as outras threads iniciar a execuo.
Thread.currentThread().yield();
System out println("Main feito");
System.out.println("Main
}
}
Iniciando threads...
Main feito
Thread de alta prioridade executando -> 10
Thread de alta prioridade executando -> 10
Thread de baixa prioridade executando -> 1
Thread de baixa prioridade executando -> 1
Thread de baixa prioridade executando -> 1
Thread de alta prioridade executando -> 10
Thread de alta prioridade executando -> 10
Thread de baixa prioridade executando -> 1
:
INE-CTC-UFSC

Cada thread pertence a um grupo de threads. Um thread


group um conjunto de threads com mecanismos para
desempenhar operaes em todos membros do conjunto.
z Se no definido, toda thread criada pertence ao grupo
'main'.

stop()
suspend()
resume()

stop()
suspend()
resume()

ThreadGroup A
Thread A1
Thread A2
:
Thread An

ThreadGroup B
Thread B1
Thread B2
:
Thread Bn

class MinhaThread2 implements Runnable {


public void run() {
System.out.println("Bom Dia !");
}
}
15

INE-CTC-UFSC

Grupo de Threads

16

Sincronizao de Threads
|

Criando um grupo de threads:


z ThreadGroup(String name)
z ThreadGroup(ThreadGroup parent, String
name)

Criando uma thread dentro de um thread group especfico:


Th
ThreadGroup
dG
meuGrupo
G
= new Th
ThreadGroup("Grupo
dG
("G
A");
Thread novaThread = new Thread(meuGrupo,
umObjRunnable, "Thread 11");
umObjRunnable: objeto alvo cujo mtodo run()
executado.
Para saber qual grupo uma thread pertence use o mtodo
getThreadGroup() e depois getName().

14

INE-CTC-UFSC

17

Quando muitas threads so executadas muitas vezes necessrio sincronizar suas


atividades, por exemplo:
z Prevenir o acesso concorrente a estruturas de dados no programa que so
compartilhados entre as threads;

class MeuDado {
private int Dado;
public void armazenar(int Dado) {
this.Dado=Dado;
;
}
public int carregar() {
return this.Dado;
}
}
class Main {
public static void main(String argv[]) {
MeuDado dado = new MeuDado();
new Thread(new Produtor(dado)).start();
new Thread(new Consumidor(dado)).start();
}
}
INE-CTC-UFSC

18

Sincronizao de Threads: Problema

Sincronizao de Threads: Problema

class Produtor implements Runnable {


MeuDado dado;
public Produtor(MeuDado dado) {
this.dado=dado;
}
public void run() {
int i;
for(i=0;i<30;i++) {
dado arma enar(i)
dado.armazenar(i);
System.out.println ("Produtor: "+i);
try {
// cochila por um tempo randmico (0 to 0.5 sec)
Thread.sleep((int)(Math.random()*500));
} catch (InterruptedException e) { }
}
}
}

INE-CTC-UFSC

class Consumidor implements Runnable {


MeuDado dado;
public Consumidor(MeuDado dado) {
this.dado=dado;
}
public void run() {
for(int i=0;i<30;i++) {
System.out.println("Consumidor: "+dado.carregar());
tr {
try
// cochila por um tempo randmico (0 to 0.5 sec)
Thread.sleep((int)(Math.random()*500));
} catch (InterruptedException e) { }
}
}
}

19

INE-CTC-UFSC

Sincronizao de Threads: Soluo 1


class MeuDado {
private int Dado;
private boolean Pronto;
private boolean Ocupado;
public MeuDado() {
Pronto = false;
Ocupado = true;
}
public void armazenar(int Dado) {
while(!Ocupado);
this.Dado=Dado;
Ocupado = false;
Pronto = true;
}
public int carregar() {
int Dado;
while(!Pronto);
Dado = this.Dado;
// armazena o valor porque uma vez
Pronto = false;
// ocupado "true" ele pode mudar
Ocupado = true;
// em qualquer tempo.
return Dado;
}
}
INE-CTC-UFSC

Sincronizao usando Monitores


|

Java suporta sincronizao de threads atravs do uso de


monitores.
Um monitor um inibidor, como um token que uma thread
pode adquirir e liberar:
z Um monitor associado com um objeto especfico e
funciona como uma tranca nesse objeto;
z Uma thread pode adquirir o monitor (ou token) de um
objeto se nenhuma outra thread tiver ele, e pode liber-lo
quando quiser.
Regio crtica: um segmento de cdigo, dentro de um
programa, que no deve ser acessado concorrentemente.
z Em Java, esse segmento de cdigo declarado usando a
palavra chave synchronized.

21

INE-CTC-UFSC

Sincronizao usando Monitores

22

Sincronizao usando Monitores


class MeuDado {
private int Dado;
private boolean Pronto;
private boolean Ocupado;

| Declarando uma seo de cdigo sincronizada:


void minhaClasse() {
// cdigo no sincronizado
...
synchronized(objCujoMonitorParaSerUsado) {
// bloco sincronizado
...
}
// mais cdigo no sincronizado
...
}
| Declarando um mtodo todo sincronizado:
synchronized meuMetodo(...) {
// bloco sincronizado
...
}
INE-CTC-UFSC

20

public MeuDado() {
Pronto=false;
Ocupado=true;
}
public
pub
c sy
synchronized
c o
ed void
o d a
armazenar(int
a e a ( t Dado)
ado) {
while(!Ocupado);
this.Dado=Dado;
Ocupado=false;
Pronto=true;
}
public synchronized int carregar() {
while(!Pronto);
Pronto=false;
Ocupado=true;
return this.Dado;
}
}

23

INE-CTC-UFSC

24

Sincronizao usando Monitores


|

Sincronizao usando eventos

Cdigo corrigido

Ocupado=true;
return this.Dado;

class MeuDado {
private int Dado;
private boolean Pronto;
private boolean Ocupado;

}
}

public MeuDado() {
Pronto=false;
}

Comentrio:
Tem que fornecer um objeto
para o synchronized;
No adequado usar loop
busy-wait (ver while), pois
usa o processador.

INE-CTC-UFSC

public synchronized void


armazenar(int Data) {
while (Pronto)
try {
wait();
} catch (InterruptedException e) { }
this.Dado=Data;
Pronto=true;
notify();
}
public synchronized int carregar() {

25

INE-CTC-UFSC

Barreira de sincronizao
|

|
|

while (!Pronto)
try {
wait();
} catch
(InterruptedException e) { }
Pronto=false;
notify();
return this.Dado;
}
}

class MeuDado {
private int Dado;
private boolean Pronto;

public MeuDado() {
Pronto=false;
Ocupado=true;
}
public void armazenar(int Dado) {
while(!Ocupado);
synchronized(this) {
this.Dado=Dado;
Ocupado=false;
Pronto=true;
}
}
public int carregar() {
while(!Pronto);
synchronized(this) {
Pronto=false;

Faz uso dos mtodos wait() e notify() para gerar eventos de espera e
notificao para parar de esperar.

26

Barreira de sincronizao

Permite sincronizar varias threads em um ponto especfico do


cdigo.
z Usada em aplicaes onde todas as threads devem
terminar uma fase antes de mover todas juntas para a
prxima fase.
Uma thread q
que alcana
a barreira automaticamente wait();
();
Quando a ltima thread alcana a barreira ele notifyAll()
todas threads em espera.

import java.util.*;
class Barreira {
private int ThreadsParticipante;
private int EsperandoNaBarreira;
public Barreira(int num) {
ThreadsParticipante = num;
EsperandoNaBarreira = 0;
}
public synchronized void Alcanado() {
EsperandoNaBarreira++;
if(ThreadsParticipante != EsperandoNaBarreira) {
try {
wait();
catch (InterruptedException e) {}
} else {
notifyAll();
EsperandoNaBarreira=0;
}
}
}

INE-CTC-UFSC

27

INE-CTC-UFSC

28

Esperando uma thread terminar


|

Algumas vezes necessrio esperar a terminao de uma


thread, por exemplo, a thread principal (main) pode lanar
uma thread secundria para processar uma tarefa

INE-CTC-UFSC

29

Você também pode gostar