Buscar

aula_02_Threads

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 47 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 47 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 47 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Programação Concorrente
Threads em Java
Prof. Antonio Felipe Podgorski Bezerra, M.Sc.
afbezerra@unicarioca.edu.br
Sumário
´ Executar tarefas simultaneamente utilizando 
Threads.
´ Entender o escalonador de Threads.
´ Problemas com concorrência e sincronismos 
em Threads.
´ Exercícios práticos
Threads
´ A maioria dos programas são escritos de modo 
sequencial com um ponto de início (método 
main( )), uma sequência de execuções e um 
ponto de término.
´ Em qualquer dado instante existe apenas uma 
instrução sendo executada.
´ O que são Threads?
´ É um simples fluxo sequencial de execução que 
percorre um programa.
´ Multithreading: o programador especifica que os 
aplicativos contêm fluxos de execução (threads), 
cada thread designando uma parte de um 
programa que pode ser executado 
simultaneamente com outras threads.
Threads
´Um thread não é somente um programa, 
mas executa dentro de um programa. É um 
fluxo único de controle sequencial dentro de 
um programa.
Threads
Thread Processo
Mais Leve Mais Pesado
Recursos compartilhados Recursos Próprios(I/O, ...)
Endereçamento compartilhado Endereçamento Próprio
Ambiente de execução 
Compartilhada 
Ambiente de Execução próprio
Existe dentro de um Processo Possui ao menos um thread
Benefícios de Thread
— A criação e terminação de uma thread nova é em 
geral mais rápida do que a criação e terminação 
de um processo novo.
— A comutação de contexto entre duas threads é 
mais rápido do que entre dois processos.
— A comunicação entre threads é mais rápida do que 
a comunicação entre processos.
— Multiprogramação usando o modelo de threads é 
mais simples e mais portável do que 
multiprogramação usando múltiplos processos.
Implementação de uma 
Thread
Existem duas formas de criar explicitamente 
um thread em Java:
— Estendendo a classe Thread e instanciando 
um objeto desta nova classe.
— Implementando a interface Runnable e 
passando um objeto desta nova classe 
como argumento do construtor da classe 
Thread.
Nos dois casos a tarefa a ser executado pelo 
thread deverá ser escrita no método run( ).
Implementação de uma 
Thread
— Em Java, usamos a classe Thread do 
pacote java.lang para criarmos linhas de 
execução paralelas. 
— A classe Thread recebe como argumento 
um objeto com o código que desejamos 
rodar. 
— Por exemplo, no programa de PDF e barra 
de progresso:
Implementação de uma 
Thread
public class GeraPDF {
public void rodar( ) {
// lógica para gerar o pdf...
}
}
public class BarraDeProgresso {
public void rodar( ) {
// mostra barra de progresso e atualizando...
}
}
Implementação de uma 
Thread
— E, no método main, criamos os objetos e 
passamos para a classe Thread. O método 
start é responsável por iniciar a execução 
da Thread:
public class MeuPrograma {
public static void main (String[] args) {
GeraPDF gerapdf = new GeraPDF();
Thread threadDoPdf = new Thread(gerapdf);
threadDoPdf.start();
BarraDeProgresso barraDeProgresso = new BarraDeProgresso();
Thread threadDaBarra = new Thread(barraDeProgresso);
threadDaBarra.start();
}
Porém, o código não compilará.
Como a classe Thread sabe que deve chamar 
o método public void rodar ( )? 
Como ela sabe que nome de método 
daremos e que ela deve chamar esse 
método especial?
Falta na verdade um contrato entre as nossas 
classes a serem executadas e a classe Thread.
Implementação de uma 
Thread
— Esse contrato existe e é feito pela interface 
Runnable: devemos dizer que nossa classe 
é “executável” e que segue esse contrato.
— Na interface Runnable, há apenas um 
método chamado run( ).
— Basta implementá-lo, “assinar” o contrato e 
a classe Thread já saberá executar nossa 
classe:
Implementação de uma 
Thread
public class GeraPDF implements Runnable {
@Override 
public void run( ) {
// lógica para gerar o pdf...
}
}
public class BarraDeProgresso implements Runnable {
@Override 
public void run( ) {
// mostra barra de progresso e atualizando...
}
}
Implementação de uma 
Thread
— A classe Thread recebe no construtor um 
objeto que é um Runnable, e seu método 
start chama o método run da nossa classe.
— Repare que a classe Thread não sabe qual 
é o tipo específico da nossa classe; para 
ela, basta saber que a classe segue o 
contrato estabelecido e possui o método 
run.
— É o bom uso de interfaces, contratos e 
polimorfismo na prática!
Implementação de uma 
Thread
— A classe Thread implementa Runnable. 
Então, você pode criar uma subclasse dela 
e reescrever o run que, na classe Thread, 
não faz nadasse.
public class GeraPDF extends Thread {
public void run( ) {
// to do:
}
}
Implementação de uma 
Thread
— E, como nossa classe é uma Thread,
podemos usar o start diretamente:
GeraPDF gera = new GeraPDF();
gera.start( );
— Apesar de ser um código mais simples,
você está usando herança apenas por
“preguiça” (herdamos um monte de
métodos mas usamos apenas o run), e
não por polimorfismo, que seria a
grande vantagem. Prefira implementar
Runnable a herdar de Thread.
Solução Baseada em 
Herança da Classe Thread
Thread
GeraPDF instanciação
Implementação de uma 
Thread
public class Programa implements Runnable {
private int id;
public void setId(int id) {
this.id = id;
}
@Override
public void run( ) {
for (int i = 0; i < 10000; i++) {
System.out.println("Programa " + id + " valor: " +
i);
}
}
}
Implementação de uma 
Thread
public class Threads {
public static void main(String[] args) {
Thread t1 = new Thread(new Programa());
t1.start();
Thread t2 = new Thread(new Programa());
t2.start();
}
}
Solução Baseada na 
Interface Runnable
Thread
Programa Runnable
referência
Classe A
Exercícios práticos
1) Crie a classe GeradorRelatorio, que 
contém o código a ser executado por uma 
thread:
Exercícios práticos
2) Implemente o código para Criação e 
execução de uma Thread, usando um objeto 
GeradorRelatorio:
Exercícios práticos
3) Altere o código de execução de thread, 
desenvolvido no exercício anterior, incluindo 
a mensagem final:
Resultado da execução
— Por que a mensagem final aparece antes 
da execução da Thread?
— Thread == novo processo independente
Exercícios práticos
4) Crie a classe BarraDeProgresso, que será 
executada por uma Thread, durante a 
impressão do relatório:
Exercícios práticos
5) Agora, nossa aplicação deve imprimir o 
relatório e exibir a barra, ao mesmo tempo:
Resultado da execução
— Os processos concorrem por tempo de 
execução no processador;
— As regras de escalonamento definem o 
tempo de execução de cada processo.
Escalonador e trocas de 
contexto
— É serviço do escalonador de 
threads(scheduler) alternar o tempo de 
execução de cada Thread iniciada(start).
— A troca de contexto ocorre quando o 
escalonador salva o estado da thread 
atual, para recuperar depois, e pára sua 
execução.
— Neste momento, é iniciada uma nova
thread.
— ou é recuperado o estado de outra que 
estava parada, voltando a executar;
Escalonador e trocas de 
contexto
— Se rodarmos o exemplo dos slides 17 e 18, qual será a 
saída?
— De um a mil e depois de um a mil?
— Provavelmente não, senão seria sequencial. 
— Ele imprimirá 1 de t1, 1de t2, 2 de t1, 2 de t2, 3 de t1 e 
3 de t2 e etc... Exatamente intercalado?
— Na verdade, não sabemos exatamente qual é a 
saída.
— Se executar o programa várias vezes, observará que 
em cada execução a saída é um pouco diferente.
Ciclo de vida
Prioridades em Threads
— Cada thread possui uma prioridade de execução 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.
— A thread de maior prioridade preempta as outras 
threads de menor prioridade.
Escalonamento
Fonte: Java, Como programar. 
Deitel, 6ª Edição
Prioridades em Threads
— Se todas as threads tiverem a mesma 
prioridade, a CPU é alocada para todos, 
um de cada vez, em modo round-robin.
— getPriority(): obtém a prioridade corrente 
da thread;
— setPriority(): define uma nova prioridade.
Prioridades em Threads
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);
}
}
}
}
Prioridades em Threads
class Lançador {
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 execução.
// O método yield(), cede o processamento para outra thread.
Thread.currentThread().yield();
System out println("Main feito");
}
}
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
Problemas com 
Concorrência Sincronização 
de Threads
— Quando muitas threads são executadas 
muitas vezes é necessário sincronizar suas 
atividades.
— Por exemplo, prevenir o acesso 
concorrente a estruturas de dados 
(variáveis, vetores, matrizes etc.) no 
programa que são compartilhados entre as 
threads;
Interferência entre Threads
— Erros introduzidos quando múltiplas threads 
acessam um dado compartilhado.
— Essa interferência pode fazer com que o 
resultado não seja esperado.
Interleaving
— Interferência acontece quando duas 
operações, rodando em threads diferentes, 
atuam sobre o mesmo objeto. 
— Interleaving significa que os passos 
realizados pelas operações se sobrepõem
— De forma não-determinística.
Exercícios práticos
— Imagine que temos a necessidade de 
imprimir os nomes das frutas de um cesto;
— Queremos “dar um tempo” para a leitura 
dos usuário;
— Com isso, precisamos que, após a 
impressão de um nome, seja realizada uma 
pausa na execução;
— Para isso, usamos Thread.sleep(tempo).
Exercícios práticos
6) Cria a cesta de frutas:
public class CestaFrutas implements Runnable {
@Override
public void run() {
//Criação da lista de frutas
String [ ] ingredientes = {"Banana", "Mamão", "Maçã", "Abacate"};
System.out.println("Início do Run()");
//Impressão da lista de frutas
for (String fruta : ingredientes) {
System.out.println(fruta);
//Dormindo por 3 segundos
try {
Thread.sleep(3*1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
System.out.println("Fim do Run()");
} 
}
Exercícios práticos
7) Implemente e execute o código a seguir:
8) Qual o resultado?
public class ThreadCestaFrutas {
public static void main(String[] args) {
//Criação do objeto executável
CestaFrutas salada = new CestaFrutas();
//Criação da Thread
Thread executar = new Thread(salada);
//Execução da Thread
executar.start();
}
}
Exercícios práticos
— Consultando a documentação java, 
verificamos que a classe Thread
implementa Runnable.
— Isso nos permite criar uma classe filha de 
Thread e sobrescrever o método run().
— Isso nos permite colocar na mesma classe o 
executor e o executado.
Exercícios práticos
8) Implemente a herança de Thread.
Garbage Collector
— O Garbage Collector (coletor de lixo) é
uma Thread responsável por jogar fora
todos os objetos que não estão sendo
referenciados;
— Imaginemos o código a seguir:
Garbage Collector
— Com a execução do item 1, são criados
dois objetos ContaBancaria e atribuídos às
referências conta1 e conta2.
— No item 2, as duas referências passam a
apontar para o mesmo objeto.
— Neste momento, quantos objetos existem
na memória? Um ou dois?
— Perdemos a referência a um dos objetos.
Garbage Collector
— O objeto sem referência não pode mais ser
acessado.
— Podemos afirmar que ele saiu da memória?
— Como Garbage Collector é uma Thread, por
ser executado a qualquer momento.
— Com isso, dizemos que o objeto sem
referência está disponível para coleta.
Garbage Collector
— Você consegue executar o Garbage
Collector.
— Mas chamando o método estático
System.gc() você está sugerindo que a JVM
rode o Garbage Collector naquele
momento.
— Sua sugestão pode ser aceita ou não.
— Você não deve basear sua aplicação na
execução do Garbage Collector.
DÚVIDAS?

Outros materiais