• Nenhum resultado encontrado

Threads

N/A
N/A
Protected

Academic year: 2021

Share "Threads"

Copied!
27
0
0

Texto

(1)

1 Cesar Rocha alunoscesar@gmail.com Cesar Rocha Cesar Rocha alunoscesar@gmail.com alunoscesar@gmail.com

(2)

2

Objetivos

§ Explorar os conceitos do uso das ThreadsThreads e sua importância em aplicações multithreads

§ Como criar e gerenciar threads, métodos da API Java,

sincronismo, classe Thread e interface Runnable

§ Escalonamento de threads, conceito de processos ambiente de execução e boas práticas usando Java

§ Alguns problemas relacionados com o uso de

threads: e.g. corrupção de dados (concorrência)

§ Exercícios e vários exemplos de códigos que você

deve testar visando solidificar seus conhecimentos

(3)

3

Ambientes multithreads

§ Ambientes multithreads representam uma nova

forma de enxergar o funcionamento de um software

§ Sistemas de software multithreads desempenham

várias atividades de maneira concorrente

§ Estes softwares são capazes de dividir, corretamente, um problema em tarefas menores e independentes

§ Aplicações multithread comuns no nosso dia-a-dia: § Browser, jogos, servidor Web, coletor de lixo, etc...

§ O suporte a multithreading de Java é nativo § Relativamente fácil de usar do que em outras

(4)

4

Processos vs. Threads

§ Um processo pode ser entendido como o ambiente onde se pode executar um programa no S.O.

§ O processo é quem irá definir o ambiente, regras, os

seus recursos (buffers, variáveis de ambiente, cópia dos registradores, arquivos, ...) disponíveis a um programa

§ Programa e processo são dois conceitos distintos:

§ Programa = código e processo = a execução

§ Um processo pode chamar vários outros processos (abrir um programa a partir do prompt do DOS, gerando outro processo na memória, por exemplo)

(5)

5

Processos vs. Threads

§ Foi visto que um processo é a execução de um

programa juntamente com seus recursos usados

§ A parte “passiva” corresponde aos recursos alocados na hora de iniciar o processo

§ A parte “ativa” corresponde ao fluxo de controle do processo – ou sua linha de execução

§ Um processo pode disparar várias linhas de

execução independentes (chamadas de threads)

§ Elas compartilharão a mesma área de endereçamento

§ Por que não criar outro processo?

§ Existe uma sobrecarga do SO para criar e destruir novos (sub)processos (memória, recursos gerais, etc.)

(6)

6

Threads em Java

§ São diferentes linhas de execução (independentes) dentro de um de um processo que roda o programa

§ Também são conhecidas como lightweight process § Um thread “fala e anda” como um programa individual

§ Threads, em Java, são objetos!

§ Sistema garante que, de alguma forma, cada thread tenha acesso à CPU de acordo com:

§ Cotas de tempo (time-slicing), Preempção, ...

§ Programador pode controlar parcialmente forma de

(7)

7

Por que usar múltiplas threads?

§ Todo programa tem pelo menos uma thread, que é

conhecida como Main Thread.

§ O método main() roda no Main Thread

§ Em alguns tipos de aplicações, threads adicionais são fundamentais, como:

§ Interfaces gráficas

§ Essencial para ter uma interface ao usuário que

responda enquanto outra tarefa está sendo executada

§ Rede

§ Essencial para que o servidor possa continuar a esperar por outros clientes enquanto lida com as requisições do cliente previamente conectado.

(8)

8

Declarando threads em Java

§ Basicamente, existem duas formas possíveis de se criar uma thread em Java:

§ Crie uma classe que herde de java.lang.Thread

§ Implemente a interface java.lang.Runnable

§ Ao herdar da classe Thread:

§ O objeto é um Thread, e sobrepõe o comportamento padrão associado à classe Thread (pouco recomendado)

§ Ao implementar a interface Runnable:

§ O objeto, que define o comportamento da execução, é passado para um Thread que o irá executar (mais recomendado)

§ Nos dois casos:

§ Sobreponha o método run() que é o "main()" do Thread

§ O run() deve conter um loop que irá rodar pelo tempo de vida

(9)

9

Exemplo com Thread

public class UsaSapateiro {

public static void main( String[] args ) { Thread sc = new Sapateiro();

sc.start();

System.out.println( "Fim do método main()" ); }

}

public class UsaSapateiro {

public static void main( String[] args ) { Thread sc = new Sapateiro();

sc.start();

System.out.println( "Fim do método main()" ); }

} public class Sapateiro extends Thread {

public Sapateiro(){ this.setName("Sapateiro Comum:"); } public void run() {

for (int marteladas = 1; marteladas <= 10; marteladas++) System.out.println(this.getName() +

" (martelada): " + marteladas ); }

}

public class Sapateiro extends Thread {

public Sapateiro(){ this.setName("Sapateiro Comum:"); }

public void run() {

for (int marteladas = 1; marteladas <= 10; marteladas++) System.out.println(this.getName() +

" (martelada): " + marteladas );

}

}

Não garante a execu Não garante a execuçção ão

imediata! imediata!

Dica:

Dica: o méo método runtodo run() de uma thread () de uma thread equivale ao

equivale ao mainmain() de uma classe() de uma classe

Qual é a saída do programa?

Qual

Qual éé a a sasaíídada do do programaprograma??

Observe alguns Observe alguns m méétodos de todos de Thread Thread

(10)

10

Exemplo com Runnable

public class UsaSapateiro {

public static void main( String[] args ) {

Thread sc = new Thread(new SapateiroRunnable()); sc.start();

System.out.println( "Fim do método main()" ); }

}

public class UsaSapateiro {

public static void main( String[] args ) {

Thread sc = new Thread(new SapateiroRunnable()); sc.start();

System.out.println( "Fim do método main()" ); }

} public class SapateiroRunnable implements Runnable { public void run() {

for (int marteladas = 1; marteladas <= 10; marteladas++) System.out.println("Sapateiro Runnable (martelada):"

+ marteladas ); }

}

public class SapateiroRunnable implements Runnable {

public void run() {

for (int marteladas = 1; marteladas <= 10; marteladas++) System.out.println("Sapateiro Runnable (martelada):"

+ marteladas );

}

}

Runnable funciona como Runnable funciona como

o

o ““trabalhotrabalho”” da threadda thread

Qual é a saída do programa?

Qual

Qual éé a a sasaíídada do do programaprograma??

Runnable s

Runnable sóó possui possui um m

um méétodo: todo: runrun()()

(11)

11

Declarando threads em Java

§ Como foi visto, a escolha fica entre herdar da classe Thread ou implementar a interface Runnable

§ A primeira abordagem fere alguns conceitos de OO

(herança == especialização de classes)

§ Use herança de tipos para adicionar comportamentos

§ O código (ou o trabalho a ser realizado pela thread) deve ficar dentro do método run()

§ Para disparar uma nova Thread, instancie o objeto e depois envie start() para ele

§ Cuidado! Não chame run() diretamente, ou você estará

(12)

12 pú bl ic o in te rn o

Não-determinismo

§ Observe a saída: Acesso proibido! Acesso proibido!

public class UsaSapateiro {

public static void main( String[] args ) {

Thread sr = new Thread( new SapateiroRunnable() ); sr.start();

Thread sc = new Sapateiro(); sc.start();

System.out.println( "Fim do método main()" ); ...

public class UsaSapateiro {

public static void main( String[] args ) {

Thread sr = new Thread( new SapateiroRunnable() ); sr.start();

Thread sc = new Sapateiro(); sc.start();

System.out.println( "Fim do método main()" ); ...

Observe os pontos críticos!

Observe

Observe osos pontospontos crcrííticosticos!!

Como pode

Como pode mainmain() ter () ter terminado primeiro? terminado primeiro?

Por que houve uma intercala Por que houve uma intercalaçção ão

das threads, no final? das threads, no final?

(13)

13

Estados de transição de uma thread

§ Linhas de execução podem ser:

Œ Novas: o objeto foi instanciado (new), mas não

iniciado com start()

Passíveis de execução: estão prontas para serem escalonadas pelo sistema operacional ou estão

executando no momento (não há como diferenciar)

Ž Bloqueadas: aguardando o término de uma operação

de E/S, executando um sleep(), executou um

wait() sobre um objeto, bloqueada ao tentar usar um

objeto bloqueado

(14)

14

Ciclo de vida

§ Uma thread está geralmente em um dentre três

estados: executável (e possivelmente executando) e

não-executável (esperando, bloqueado,...)

§ A thread entra no estado executável com start() que causa o início de run(), e passa para o estado morto quando run() chega ao fim.

(15)

15

Fila de prioridades

§ O estado ready não é garantia de execução. Threads são regidos por prioridades:

(16)

16

Principais métodos da classe Thread

§ Estáticos

§ Thread currentThread(): retorna referência para a thread que está executando no momento

§ void sleep(long tempo): faz com que a thread que está

executando pare por um tempo (milissegundos) no mínimo

§ void yield(): faz com que a thread atual pare e permita que outras que estão na sua fila de prioridades executem

§ De instância

§ void run(): é o "main" da Thread. Deve ser implementado na Thread ou no objeto Runnable passado à thread

§ void start(): faz o JVM chamar o run()

(17)

17

Sincronismo

§ Até aqui, as threads que vimos eram independentes

§ Não requerem acesso a recursos externos (arquivos,...) § Não precisavam se preocupar com o que estava

ocorrendo com as outras threads em execução

§ Em algumas situações, porém, threads devem compartilhar recursos limitados do sistema

§ E serão obrigadas a se preocupar com outras threads § Dados podem ser corrompidos se uma thread deixar

um objeto num estado incompleto para outra thread

§ Uma thread tentando ler um arquivo enquanto a outra está tentando gravar um dado no mesmo arquivo

(18)

18

Sincronismo

§ Num sistema, recursos limitados podem vir a ser compartilhados por várias threads simultaneamente

§ Cada objeto têm um bloqueio que pode ser acionado

pelo método que o acessa/modifica para evitar corrupção de dados

§ O escalonamento é um evento não controlado e imprevisível!

(19)

19

Sincronismo

§ Recursos compartilhados devem ser protegidos

§ A palavra synchronized permite que blocos sensíveis ao acesso simultâneo sejam protegidos de corrupção

impedindo que objetos os utilizem ao mesmo tempo.

§ Synchronized deve limitar-se aos trechos críticos

(20)

20

Comunicação entre Threads

§ Se um recurso crítico está sendo usado, só uma thread tem acesso. É preciso que:

§ Os outros esperem até que o recurso esteja livre

§ O thread que usa o recurso avise aos outros que o liberou

§ Esse controle é possível através de dois métodos da classe Object, que só podem ser usados em blocos synchronized, veja:

§ wait(): faz com que a Thread sobre a qual é chamado espere por um tempo indeterminado, até receber um... § notify(): notifica a próxima Thread que o recurso

bloqueado foi liberado. Se há mais threads interessadas, use.. § notifyAll(): avisa a todos os threads.

(21)

21

Exemplo: produtor e consumidor

§ O seguinte exemplo contém uma classe que denota um recurso compartilhado por duas threads

§ Como os métodos produzir() e consumir() contém

códigos que podem corromper os dados, se não forem executados atomicamente, eles são synchronized

§ A classe tem um local compartilhado para armazenar um

número a ser acessado/modificado por duas threads

§ Para que o exemplo fique interessante…

§ Uma thread (lenta) que irá produzir() 10 números

inteiros e armazená-los no único recurso compartilhado

§ Uma thread (apressada) quer consumir() o número imediatamente

(22)

22

Exemplo: produtor e consumidor(1)

§ A thread Produtor irá gerar 10 números e armazená-los no recurso tão logo eles forem consumidos

§ Note que há um retardo de 2 seg. a cada número gerado public class Produtor implements Runnable {

RecursoCompartilhado recurso;

public Produtor( RecursoCompartilhado r ){ this.recurso = r;

}

public void run() {

for ( int i = 1; i <= 10; i++ ) {

recurso.produzir( i ); try { Thread.sleep(2000); } catch (InterruptedException e) { } } } }

A thread tem uma

A thread tem uma

referência para recurso

referência para recurso

compartilhado

compartilhado

O for() ir

O for() iráágerar os 10 gerar os 10 n

núúmeros em seqmeros em seqüüênciaência O m

O méétodo todo sleepsleep() ir() iráá retardar a produ

(23)

23

Exemplo: produtor e consumidor(2)

§ A thread Consumidor irá tentar consumir o número em recurso compartilhado imediatamente

§ E se Produtor não tiver gerado o número ainda (lento)? public class Consumidor implements Runnable {

RecursoCompartilhado recurso;

public Consumidor (RecursoCompartilhado r) {

this.recurso = r; }

public void run() {

int numero;

for (int i = 1; i <= 10; i++) { numero = recurso.consumir(); }

} }

A thread tem uma

A thread tem uma

referência para recurso

referência para recurso

compartilhado

compartilhado

Note

Note quequenãonão hháá retardos

(24)

24

Exemplo: produtor e consumidor(3)

§ A classe recurso compartilhado (parte 1):

public class RecursoCompartilhado {

int numero; // variável que guarda o número

boolean disponivel = false; // numero disponível ou não public synchronized int consumir(){

while (disponivel == false) {

try { //espere até que produtor gere um valor

wait();

} catch (InterruptedException e) { } }

disponivel = false;

System.out.println("Consumido: " + numero);

// notifique produtor que um numero foi consumido

notifyAll();

return numero; }

public class RecursoCompartilhado {

int numero; // variável que guarda o número

boolean disponivel = false; // numero disponível ou não public synchronized int consumir(){

while (disponivel == false) {

try { //espere até que produtor gere um valor

wait();

} catch (InterruptedException e) { } }

disponivel = false;

System.out.println("Consumido: " + numero);

// notifique produtor que um numero foi consumido

notifyAll(); return numero; } M ét od o co ns um ir ... a classe continua...

(25)

25

Exemplo: produtor e consumidor(4)

§ A classe recurso compartilhado (parte 2):

...

public synchronized void produzir( int numero ) { while (disponivel == true) {

try { //espere que consumidor pegue o numero

wait(); } catch (InterruptedException e) { } } this.numero = numero; disponivel = true; System.out.println("Produzido: " + numero);

//notifique consumidor que um numero foi gerado

notifyAll();

}

}// classe

...

public synchronized void produzir( int numero ) { while (disponivel == true) {

try { //espere que consumidor pegue o numero

wait();

} catch (InterruptedException e) { } }

this.numero = numero; disponivel = true;

System.out.println("Produzido: " + numero);

//notifique consumidor que um numero foi gerado

notifyAll(); } }// classe M ét od o pr od uz ir

(26)

26

Em resumo…

§ Como sincronizar threads concorrentes?

§ Threads ganham acesso a um recurso adquirindo seu monitor (uma espécie de trava/chave ou “lock”)

§ Somente com o monitor em mãos é que a thread pode acessar partes restritas do código que é crítico

§ Cada objeto Java possui um monitor associado

§ Alguns métodos em um objeto podem exigir um monitor

para serem executados (produzir, consumir, como vimos)

§ Apenas uma thread pode executá-los por vez

§ Haverá um bloqueio do objeto para outras threads

§ Estes métodos são chamados sincronizados

§ Declarados com synchronized

§ Apenas uma thread pode executar um método sincronizado de um objeto por vez (mesmo se houver escalonamento)

(27)

27

Para um bom aproveitamento:

Para um bom aproveitamento:

§ Codifique os exemplos mostrados nestes slides e verifique pontos de dúvidas

§ Resolva todas as questões da lista de Threadslista de Threads § Procure o professor ou monitor da disciplina e

questione conceitos, listas, etc.

§ Não deixe para codificar tudo e acumular assunto

para a avaliação.

Referências

Documentos relacionados

BARHAM, 1982 (2), define as diferenças conceituais e campos de ação, tanto para en­ sino como investigação, entre Biomecânica e Cinesiologia Mecânica. Não trataremos

A meta prevista para este indicador era garantir a realização de exames complementares em dia a 100% de hipertensos e diabéticos do programa, por tanto não foi atingida,

2016: SEMINÁRIO EM ANTA GORDA: INÍCIO DO PLEITO PARA CÂMARA SETORIAL E PROGRAMA Seminário e reuniões na SEAPI para construção.. do

Lernaea cyprinacea of Steindachnerina insculpta from Taquari River, municipality of Taquarituba, São Paulo State, Brazil.. Note the hemorrhagic area around the insertion point of

Note on the occurrence of the crebeater seal, Lobodon carcinophagus (Hombron &amp; Jacquinot, 1842) (Mammalia: Pinnipedia), in Rio de Janeiro State, Brazil.. On May 12, 2003,

◦ Os filtros FIR implementados através de estruturas não recursivas têm menor propagação de erros. ◦ Ruído de quantificação inerente a

Os candidatos reclassificados deverão cumprir os mesmos procedimentos estabelecidos nos subitens 5.1.1, 5.1.1.1, e 5.1.2 deste Edital, no período de 15 e 16 de junho de 2021,

potencialmente porque não são entendidos como tal pela maioria da população e porque não estão classificados — e, em parte, a uma lacuna consistente relativa à formação de