Sie sind auf Seite 1von 58

Programao Orientada a Objetos

Threads
Prof. Esp. Flvio Almeida Ferreira
Prof. Esp. Flvio Almeida Ferreira

Sumrio

O que so Threads
Multithreads
Porque utilizar threads
Utilizando threads
Sincronismo entre threads
Principais mtodos
Mais informaes

Prof. Esp. Flvio Almeida Ferreira

O que so threads?
Threading um artifcio que permite a coexistncia de mltiplas
atividades dentro de um nico processo.
Java a primeira linguagem de programao a incluir
explicitamente o conceito de Threads na prpria linguagem.

Prof. Esp. Flvio Almeida Ferreira

O que so threads?
Threads so tambm chamados de processos leves (lightweight
processes), pois, da mesma forma que processos, threads so
independentes, possuem sua prpria pilha de execuo, seu
prprio program count e suas prprias variveis locais.
Porm, threads de um mesmo processo compartilham memria,
descritores de arquivos (file handles) e outros atributos que so
especficos daquele processo.

Prof. Esp. Flvio Almeida Ferreira

O que so threads?
Um processo pode conter mltiplas threads que parecem executar
ao mesmo tempo e de forma assncrona em relao as outras
threads.
Todas as threads de um mesmo processo compartilham o mesmo
espao de endereamento de memria, o que significa que elas
tm acesso as mesmas variveis e objetos, e que eles podem alocar
novos objetos de um mesmo heap.
Ao mesmo tempo que isso torna possvel que threads
compartilhem informaes entre si, necessrio que o
desenvolvedor se assegure que uma thread no atrapalhe a
execuo de outra.
Prof. Esp. Flvio Almeida Ferreira

O que so threads?
A API de threads em Java incrivelmente simples. Mas escrever
um programa complexo que as use de forma eficiente e correta
no to simples assim.
responsabilidade do programador impedir que uma thread
interfira de forma indesejvel no funcionamento das outras
threads do mesmo processo.

Prof. Esp. Flvio Almeida Ferreira

Todo programa em Java


multithreaded?
Todo programa em Java possui pelo menos uma thread: a main.
Alm dessa, a mquina virtual mantm algumas outras que
realizam tarefas como coleta de lixo ou finalizao de objetos.
Algumas classes disponveis na API de Java tambm utilizam
threads em suas implementaes. Como exemplo, as classes de
Java Swing ou as classes da implementao de RMI.

Prof. Esp. Flvio Almeida Ferreira

Por que utilizar threads?


Responsividade em Interfaces Grficas: imagine se o seu
navegador web parasse e carregar uma pgina s porque voc
clicou no menu arquivo;
Sistemas multiprocessados: o uso de threads permite que o SO
consiga dividir as tarefas entre todos os processadores
disponveis aumentando, assim, a eficincia do processo;

Prof. Esp. Flvio Almeida Ferreira

Por que utilizar threads?


Simplificao na Modelagem de Aplicaes: suponha que voc
precise fazer um programa que simule a interao entre
diferentes entidades. Carros em uma estrada, por exemplo.
mais fcil fazer um loop que atualiza todos os carros da
simulao ou criar um objeto carro que anda sempre que tiver
espao a frente dele?
Processamento assncrono ou em segundo plano: com threads
um servidor de e-mail pode, por exemplo, atender a mais de um
usurio simultaneamente.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Criando threads
H duas formas equivalentes de criarmos uma thread em Java:

Criando um objeto que estende a classe Thread a qual


sobrescreve o seu mtodo public void run();
Implementando a interface Runnable.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Criando threads
A sada do texto, como esperado, so as duas mensagens
intercaladas aleatoriamente na sada padro.
Dependendo do sistema operacional e dos recursos
computacionais do computador a sada pode parecer seqencial.
Esse comportamento pode ser explicado pelas propriedades das
threads.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Criando threads
Apesar das duas formas de uso de threads serem equivalentes,
classes que necessitem estender outra classe que no Thread
so obrigadas a usar a interface Runnable, j que Java no possui
herana mltipla.
Alm disso, os puristas em orientao a objetos dizem que
normalmente estamos interessados em criar classes que usem
threads e no classes que sejam threads e que, portanto,
deveramos implementar toda a lgica em uma classe que
implementa Runnable e depois criar a thread s quando for
necessrio.
Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Estados de uma thread
Uma thread pode estar em um dos seguintes estados:

Criada;
Em execuo;
Suspensa;
Morta.

Uma thread se encontra no estado criada logo aps a


instanciao de um objeto Thread. Neste ponto nenhum recurso foi
alocado para a thread.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Estados de uma thread
A nica transio vlida neste estado a transio para o estado
em execuo.
A thread passa para o estado em execuo quando o mtodo
start() do objeto chamado.
Neste ponto a thread pode ficar em execuo, se tornar
suspensa ou se tornar morta.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Estados de uma thread
Na verdade, uma thread pode estar em execuo mas, ainda
assim, no estar ativa.
Em computadores que possuem um nico processador impossvel
existirem duas threads executando ao mesmo tempo. Dessa forma
uma thread que est esperando para ser executada pode estar no
estado em execuo e ainda assim estar parada.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Estados de uma thread
A thread se torna suspensa quando um destes eventos ocorrer:

execuo do mtodo sleep();


a thread chama o mtodo wait() para esperar que uma condio
seja satisfeita;
a thread est bloqueada em uma operao de entrada/sada
(I/O).

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Estados de uma thread
A chamada ao comando sleep(int seconds) faz com que a thread
espere um tempo determinado para executar novamente.
A thread no executada durante este intervalo de tempo mesmo
que o processador se torne disponvel novamente. Aps o intervalo
dado, a thread volta ao estado em execuo novamente.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Estados de uma thread
Se a thread chamar o comando wait() ento ela deve esperar uma
outra thread avisar que a condio foi satisfeita atravs dos
comandos notify() ou notifyAll().

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Estados de uma thread
Se a thread estiver esperando uma operao de entrada/sada ela
retornar ao estado em execuo assim que a operao for
concluda.
Por fim, a thread se torna morta se o mtodo run() chegar ao fim
de sua execuo ou se uma exceo no for lanada e no for
tratada por um bloco try/catch.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Propriedades thread
Anteriormente foi dito que diversas threads podem executar
concorrentemente em um processo. Porm em sistemas
monoprocessados isso parcialmente verdade.
Conceitualmente isso que ocorre. Mas na prtica apenas uma
thread pode ocupar o processador por vez.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Propriedades thread
A mquina virtual de Java define uma ordem para que as threads
ocupem o processador de forma que o usurio tem a iluso de que
elas realmente executam concorrentemente.
A isso dado o nome de escalonamento de tarefas.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Propriedades thread
As prioridades de threads em Java podem variar entre os inteiros
Thread.MIN PRIORITY e Thread.MAX PRIORITY.
Quanto maior o inteiro, maior a prioridade. Para definir a
prioridade de uma thread necessrio chamar o mtodo
setPriority(int priority) da classe Thread aps a instanciao do
objeto.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Propriedades thread
A mquina virtual utilizar sua prioridade relativa para realizar o
escalonamento.
A mquina virtual sempre escolhe a thread com maior prioridade
relativa e que esteja no estado de execuo para ser executada.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Propriedades thread
Uma thread de menor prioridade s ser executada se a thread
atual for para o estado suspenso, se o mtodo run() terminar ou
se o mtodo yield(), cuja finalidade dar chance para que outras
threads executem, for chamado.
Se existirem duas threads de mesma prioridade esperando para
serem executadas, a mquina virtual escolher uma delas, como
em um escalonamento do tipo round-robin.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Propriedades thread
A thread escolhida continuar ocupando o processador at que
uma das seguintes condies se tornem verdadeiras:
uma thread de maior prioridade fica pronta para ser executada;

a thread atual chama yield() ou o mtodo run() termina;


o tempo reservado para a thread termina (s em SOs onde os
processos possuem um tempo mximo para permanecer no
processador para serem executados.
Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Propriedades thread
Como regra geral, podemos pensar que o escalonador escolher
sempre a thread com maior prioridade para ser executada em
determinado momento.
Porm, a mquina virtual livre para escolher uma thread de
menor prioridade para evitar espera indefinida (starvation).

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Fatia de tempo
Alguns sistemas operacionais como o GNU/Linux ou o Microsoft
Windows fornecem para cada thread fatias de tempo (timeslices), que nada mais so do que o intervalo de tempo mximo que
a thread pode ocupar o processador antes de ser obrigada a cedlo a outra thread.

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Fatia de tempo
O exemplo anterior produziria o seguinte resultado em sistemas
que no possuem fatias de tempo para suas threads:
Usando Runnable
(...) ("Usando Runnable" repetido 998 vezes)
Usando Runnable
Usando Herana
(...) ("Usando Herana" repetido 998 vezes)
Usando Herana

Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Fatia de tempo
J em um ambiente com fatias de tempo, as threads seriam
Interrompidas e o resultado da execuo seria assim:
Usando Runnable
Usando Runnable
Usando Herana
Usando Runnable
Usando Herana
Usando Herana
(...)
Prof. Esp. Flvio Almeida Ferreira

Utilizando Threads
Fatia de tempo
A especificao de Java no garante que o ambiente ter fatias de
tempo.
Fatias de tempo s ocorrero se o programa rodar em um sistema
operacional que possua essa caracterstica.
Seus programas no devem partir desse pressuposto.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


A maior parte dos programas multithreadeds necessitam que as
threads se comuniquem de forma a sincronizar suas aes. Para
isso, a linguagem Java prov locks (tambm chamados de
monitores).
Para impedir que mltiplas threads acessem um determinado
recurso, cada thread precisa adquirir um lock antes de usar o
recurso e liber-lo depois. Imagine um lock como uma permisso
para usar o recurso.
Apenas aquele que possuir a permisso poder utilizar o recurso.
Os outros devero esperar. A isso damos o nome de excluso
mtua.
Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Threads usam locks em variveis compartilhadas para realizar
sincronizaes e comunicaes entre threads. A thread que tiver o
lock de um objeto sabe que nenhuma outra thread conseguir
obter o lock deste objeto.
Mesmo se a thread que possuir o lock for interrompida, nenhuma
outra thread poder adquirir o lock at que a primeira volte a
utilizar o processador, termine a tarefa e libere o lock.
A thread que tentar obter um lock que j estiver com outra thread
ser suspensa e s voltar ao estado em execuo quando obtiver
novamente o lock.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Como exemplo, suponha uma classe que encapsula o servio de
impresso. Vrias threads de seu programa tentaro imprimir, mas
apenas uma thread por vez deve conseguir.
Sua classe, ento, seria mais ou menos assim:

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Utilizando locks
Em Java, cada objeto possui um lock. Uma thread pode adquirir um
lock de um objeto usando a palavra-chave synchronized.
Esta palavra-chave pode ser usada na declarao de mtodos
(neste caso o lock do objeto this utilizado) ou em blocos de cdigo
(neste caso, o objeto que contm o lock que ser usado deve ser
especificado).
Os seguintes usos de synchronized so equivalentes:

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Utilizando locks
Os seguintes usos de synchronized so equivalentes:

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Utilizando locks
O lock liberado automaticamente assim que o bloco synchronized
termina de ser executado.
Outra caracterstica importante sobre locks em Java que eles so
reentrantes. Isso quer dizer que uma thread pode readquirir um
lock que ela j possuir.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Utilizando locks
Veja o exemplo:

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Utilizando locks
Ao executar o mtodo entrar() a thread deve adquir o lock do
objeto this. Mas graas ao fato dos locks serem reentrantes, no foi
necessrio readquirir o lock para executar o mtodo reentrar().
O lock s ser liberado quando o mtodo entrar() terminar de ser
executado.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Utilizando locks
Tambm tarefa do synchronized garantir a visibilidade das
variveis compartilhadas. A mquina virtual de Java mantm uma
memria cache para cada uma de suas threads e uma memria
principal que acessada por todas as threads.
As atualizaes de memria ocorrem primeiro no cache e s depois
na memria principal.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Utilizando locks
Para impedir que uma thread atualize dados que so
compartilhados apenas em seu cache local, a palavrachave
synchronized obriga que os dados sejam gravados na memria
principal.

Dessa forma outras threads sempre acessam o valor mais atual


dessas variveis compartilhadas.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Variveis volteis

A palavra-chave volatile em Java serve para indicar que uma


varivel voltil. Isso significa trs coisas:
Primeiro que as operaes de leitura e escrita em variveis
volteis so atmicas, isto , duas threads no podem escrever
em uma varivel voltil ao mesmo tempo.
Segundo, as mudanas feitas em variveis volteis so
automaticamente visveis para todas as threads.
E, por ltimo, indica para o compilador que a varivel pode ser
modificada por outras threads.
Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Variveis volteis

Veja o cdigo a seguir:

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Variveis volteis

Um compilador poderia otimizar o cdigo removendo todo o bloco


dentro do if, pois sabe que a condio do if nunca ser verdadeira.
Porm isso no verdade em um ambiente multithreaded, para
impedir esse tipo de otimizao basta declarar a varivel flag como
sendo uma volatile boolean flag.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Variveis volteis

Pra uma explicao detalhada sobre o verdadeiro significado das


palavras-chave volatile e synchronized em termos do modelo de
memria do Java, leia o excerto do livro Concurrent Programming
in Java, de Doug Lea.
Doug Lea. Synchronization and the Java Memory Model. Disponvel em
http://gee.cs.oswego.edu/dl/cpj/jmm.html.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Quase todas as classes no so sincronizadas
Como sincronismo implica em uma pequena diminuio no
desempenho do cdigo (devido a obteno e liberao do lock), a
maior parte das classes de uso geral, como as classes que estendem
java.util.Collection, por exemplo, no so sincronizadas.
Isso significa que classes como HashMap no podem ser usadas por
mltiplas threads sem o uso de synchronized.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Quase todas as classes no so sincronizadas
Voc pode usar as classes que so Collection em uma aplicao
multithreaded se voc utilizar um lock toda vez que voc acessar
um mtodo em uma coleo compartilhada entre as threads.
Para cada coleo, voc deve usar o mesmo lock todas as vezes.
Normalmente utilizado o lock do prprio objeto que representa a
coleo.

Prof. Esp. Flvio Almeida Ferreira

Sincronismo entre Threads


Quase todas as classes no so sincronizadas
A classe Collections prov um conjunto de wrappers para as
interfaces List, Map e Map. Voc pode sincronizar um Map com o
mtodo Collections.synchronizedMap.
Veja a API [1] da classe Collections para mais informaes.
JavaTM2 Plataform API Specification.
http://java.sun.com/j2se/1.4.2/docs/api/.

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()
Cdigos como o do exemplo a seguir utilizam o que chamamos de
espera ativa. Ou seja, a thread fica esperando uma determinada
condio ser satisfeita dentro de um lao.
Essa soluo ruim porque a thread fica ocupando o processador
apenas para verificar se a condio j foi satisfeita ou no.

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()
A classe Object fornece os mtodos wait(), notify() e notifyAll().
Com esses mtodos Java fornece uma implementao do conceito
de monitores que no utiliza espera ativa.
Ao invs disso, esses mtodos enviam eventos para as threads
indicando se elas devem ser suspensas ou se devem voltar ao
estado em execuo.
Para utilizar quaisquer dos trs mtodos de um objeto qualquer a
thread deve possuir o lock do mesmo objeto.

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()
wait() faz a thread que chamou o mtodo dormir at que ela seja
interrompida pelo mtodo Thread.interrupt(), at que o tempo
especificado no argumento de wait() tenha passado ou at que
outra thread a notifique usando o mtodo notify() ou notifyAll().
Antes de ser suspensa, a thread libera o lock do objeto. Note,
entretanto, que a thread continuar a manter todos os outros locks
que ela possuir enquanto estiver suspensa.

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()
O mtodo notify() acorda, se existir, alguma thread que esteja
esperando um evento deste objeto (ou seja, que tenha executado o
comando wait() neste objeto).
E o comando notifyAll() acorda todas as threads que estejam
esperando neste objeto. Antes que a thread acordada possa
prosseguir, ela deve esperar a thread que a acordou liberar o lock e
obt-lo novamente.
O exemplo a seguir deve tornar esses conceitos mais claros.

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()
Ele implementa uma caixa onde um inteiro pode ser armazenado.
Se uma thread tentar armazenar um inteiro em uma caixa cheia ela
ser suspensa at que alguma thread retire o inteiro da caixa.
Do mesmo modo, se uma thread tentar retirar um inteiro de uma
caixa vazia ela ser suspensa at que uma outra thread coloque um
inteiro na caixa.
Esse um exemplo do problema do produtor/consumidor.

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()

Prof. Esp. Flvio Almeida Ferreira

Os mtodos wait(), notify() e


notifyAll()

Prof. Esp. Flvio Almeida Ferreira

Atividade

1) Elabore cinco questes objetivos com cinco alternativas. As


questes devem apresentar a resposta correta.
OBS: Entrega impressa.

Prof. Esp. Flvio Almeida Ferreira

Das könnte Ihnen auch gefallen