Thread() - LSI/USP

Propaganda
PROGRAMAÇÃO
DISTRIBUÍDA EM JAVA
Verão/2001
Aula 01
Noções básicas de redes
Threads
29.01.2001
Luciano Silva
e-mail: [email protected]
1
2
Tópicos da Aula 01








Noções básicas de redes
Conceitos básicos de processos
Concorrência e semáforos
Classes Runtime e Process
Threads
Interface Runnable
Threads concorrentes
Comunicação entre threads
3
Modelo ISO OSI
O modelo ISO OSI (Open Systems Interconnection
Reference Model) é um modelo de referência para
comunicação em redes, que identifica os vários
níveis envolvidos, dando-lhes nomes específicos e
indicando qual a função dos vários níveis.
O modelo foi projetado para permitir a
intercomunicação entre sistemas abertos, usando
regras-padrão que governam o formato, conteúdo
e significado das mensagens enviadas e recebidas.
Estas regras são chamadas de protocolos.
4
PROTOCOLOS
O modelo ISO OSI distingue dois tipos gerais de
protocolos:
 orientados a conexão (connection-oriented):
antes de trocar dados, o remetente e destinatário
primeiramente estabelecem uma conexão,
possivelmente negociando o protocolo a ser usado.
Transmitem dados e encerram a conexão.
 não orientados a conexão (connectionless): O
remetente simplesmente transmite a primeira
mensagem quando está pronto.
5
CAMADAS DO MODELO ISO
OSI
Processo A
Máquina 1
Máquina 2
Protocolo de Aplicação
7
Aplicação
6
Apresentação
5
Sessão
4
Transporte
3
Rede
2
Enlace de Dados
1
Física
Protocolo de Apresentação
Protocolo de Sessão
Protocolo de Transporte
Protocolo de Rede
Protocolo de Enlace
Protocolo Físico
Processo B
Aplicação
Apresentação
Sessão
Transporte
Rede
Enlace de Dados
Física
Rede
Formato típico de uma mensagem
no modelo ISO OSI
6
Trailer da camada de enlace
Mensagem
Header da camada de Aplicação
Header da camada de Apresentação
Header da camada de Sessão
Header da camada de Transporte
Header da camada de Rede
Header da camada de Enlace
7
Camada Física
A camada física está relacionada com a transmissão
de 0’s e 1’s. São tarefas desta camada:
 determinar quantos bits por segundo serão
enviados
 determinar se a transmissão pode ser feita em
ambas a direções simultaneamente
 armazenar informações sobre o tamanho e formato
do conector de rede, bem como o número de pinos
e significado de cada um deles
8
Camada de Enlace de Dados
A camada de enlace de dados ( Data Link ) está
relacionada com o agrupamento de bits em
unidades chamados frames e verificar se cada um
deles foi corretamente recebido.
Esta verificação pode ser feita com base nos padrões
de bits presentes no início e final de cada frame.
Este padrão é formado fazendo-se alguns cálculos
com bits, formado um resultado para verificação (
checksum ).
9
Camada de Rede
A camada de rede está relacionada principalmente
com o roteamento de uma mensagem pela rede.
Este roteamento envolve a tentativa de escolha do
melhor caminho para enviar a mensagem.
Existem dois protocolos principais para esta camada:
 X.25 , orientado a conexão
 IP ( Internet Protocol ), não orientado a conexão
10
Camada de Transporte
A camada de transporte está relacionada com controle de
recebimento de pacotes de mensagens.
Recebida uma mensagem da camada de sessão, a camada
de transporte quebra a mensagem em pedaços o
suficiente para que caibam num pacote, assinala a cada
um um número sequencial e os envia.
São protocolos típicos desta camada:
 TCP ( Transmission Control Protocol ), que é
orientado a conexão, muitas vezes utilizado com a
combinação TCP/IP
 UDP ( Universal Datagram Protocol ), que não é
orientado a conexão
11
Camada de Sessão
A camada de sessão está relacionada
principalmente com o controle do diálogo
entre as máquinas, saber que está falando e
prover facilidades para sincronização.
12
Camada de Apresentação
A camada de apresentação está relacionada com
o significado dos bits. A maioria das
mensagens não consistem somente de
seqüências aleatórias de bits, mas estruturada
de forma mais complexa. Nesta camada é
possível definir registros contendo campos e
adicionar informações sobre a estruturação
destes registros. Isto permite que máquinas
com diferentes representações internas se
comuniquem.
13
Camada de Aplicação
A camada de aplicação é uma coleção de vários
protolos para atividades comuns, tais como
correio eletrônico, transmissão de arquivos,
conexão remota, etc. São protocolos típicos
desta camada:
 HTTP ( HyperText Transfer Protocol ),
protocolo para transferência de hipertexto
 FTP ( File Transfer Protocol ), protocolo para
transferência de arquivos
 TELNET, para conexão remota
14
O modelo cliente-servidor
A idéia por trás do modelo cliente-servidor é
estruturar o sistema operacional(microkernel)
como grupo de processos cooperantes, chamados
servidores, que oferecem serviços aos processos
usuários, chamados clientes.
As máquinas clientes e servidoras normalmente
rodam sobre o mesmo microkernel. Para evitar a
complexidade dos protocolos do modelo ISO OSI,
tais como TCP/IP, o modelo cliente servidor é
usualmente é baseado em um protocolo simples do
tipo request/reply, não orientado a conexão.
15
Estrutura do modelo cliente-servidor
Camadas
Request
Cliente
Servidor
Reply
microkernel
microkernel
7
6
5
Rede
Devido à simplicidade, as chamadas de
comunicação podem ser reduzidas a:
send(destino,mensagem)
receive(remetente,mensagem)
Request/Reply
4
3
2
Enlace
1
Física
16
PROCESSOS
Processos (ou tarefas) são instâncias de um
programa. De um mesmo programa, pode-se ter
vários processos.
Uma das principais tarefas de um sistema
operacional(SO) é controlar processos. Sistemas
operacionais que conseguem controlar somente
um processo são chamados de sistemas do tipo
monotarefa. Sistemas que podem controlar mais
de um processo simultaneamente são chamados
de sistemas do tipo multitarefa.
17
CONTROLE DE PROCESSOS
Processos são controlados por um sistema
operacional a partir de informações contidas
numa estrutura chamada BCP ( Bloco de
Controle de Processo). Para cada processo existe
uma BCP.
Na BCP estão estruturadas várias informações dos
processos, tais como pid, ppid, registradores,
ponteiros de instruções, etc.
18
ESTADOS DE UM PROCESSO
Um processo pode estar num dos seguintes três
estados: pronto, ativo e suspenso.
PRONTO
escalonador
ATIVO
time-out
realização da
operação de
E/S ou comando
para pronto
SUSPENSO
solicitação de
operação
de E/S ou
comando de
suspensão
19
CONCORRÊNCIA
A quantidade de recursos de um sistema (discos,
impressora, etc) é muito menor do que a
quantidade de processos que podem acessar
estes recursos.
O principal problema desta situação ocorre quando
dois ou mais processos tentam acessar
concorrentemente um determinado recurso.
Como o sistema operacional pode gerenciar
acesso concorrente ?
20
CONTROLE DE CONCORRÊNCIA
Existem várias maneiras de se controlar
concorrência de processos. Algumas dos
mecanismos mais comuns são:
 semáforos
 monitores
 procedimentos test_and_set
21
SEMÁFOROS
Semáforos baseiam-se em estruturas para
contagem
de
acessos
concorrentes,
geralmente implementados por variáveis
inteiras.
Semáforos são manipulados por dois
procedimentos:
wait(Semáforo s)
signal(Semáforo s)
22
EXEMPLO PARA USO DE SEMÁFOROS
Considere-se um vetor V que é acessado de
dois modos: um processo que grava em V e
outro que lê informações de V.
V
Escrita
PRODUTOR
Leitura
CONSUMIDOR
23
SEMÁFOROS PARA O EXEMPLO ANTERIOR
wait(MUTEX)
altera vetor V
signal(MUTEX)
signal(PRODUZIU)
PRODUTOR
wait(PRODUZIU)
wait(MUTEX)
lê dado de V
signal(MUTEX)
CONSUMIDOR
24
PROCESSOS EM JAVA
Java já possui uma série de recursos para disparar e
gerenciar processos. É possível com estes
mecanismos:
 obter o processo de execução do interpretador
Java
 chamar comandos específicos de um sistema
operacional
 lançar e controlar lightweight processes com
estado reduzido( threads)
25
CLASSE Runtime
Classe de Java que representa e gerencia o sistema
Java em execução.
Não se pode instanciar o objeto do tipo Runtime,
pois ele já foi instanciado pelo interpretador Java.
Porém, pode-se conseguir uma referência do
processo em execução, através do método
getRuntime()
26
CLASSE Process
Classe de Java que representa um processo.
Esta classe não tem construtor, pois trata de
um objeto externo, ou seja, de um processo
que não é criado dentro do Runtime Java.
A classe Process ajuda a manipular um
processo, bem como gerenciá-lo.
27
Exemplo com classe Runtime e Process
class chama_comando_SO{
public static void main(String args[]){
Runtime r=Runtime.getRuntime();
Process p=null;
try{
p=r.exec(“/usr/bin/ls”); // chama ls do Unix
p.waitFor(); // Faz p esperar pelo final do ls
}
catch(Exception e){...}
if(p.exitValue()==0) // Verifica código de retorno do processo
System.out.println(“Tudo OK com ls”);
else System.out.println(“ls deu algum erro”);
}
}
28
THREADS
Threads são processos leves (lightweight process)
com um estado reduzido. O estado reduzido
advém do fato de um grupo de threads
compartilharem os mesmos dados.
Em um sistema com threads, um processo com
exatamente um thread é equivalente a um processo
clássico. Cada thread pertence a exatamente um
processo, compartilhando os dados do processo
que o disparou. Threads não podem existir fora de
um processo.
29
Interface Runnable
Toda classe que precisa manipular threads,
deve primeiramente implementar o método:
public void run();
definido na interface Runnable. Este método
define o que o thread disparado pela classe
deverá fazer.
30
CLASSE Thread
Classe utilizada para instanciar threads.
Instanciar não significa que o thread
começará a ser executado.
Existem, basicamente, três construtores para
threads:
Thread()
construtor-padrão
Thread(String n)
construtor com nome do thread
Thread(ThreadGroup g,String n) construtor com base num
grupo de threads e nome n
31
Alguns métodos iniciais da classe
boolean isAlive()
boolean isDaemon()
void start()
void stop()
void supend()
void resume()
void sleep(long t)
void setName(String s)
void setPriority(int p)
verifica se thread está ativo
verifica se thread é um daemon
inicia a execução do thread
para o thread
suspende o thread
retoma thread suspenso
deixa thread “dormindo”por
t milisegundos
muda nome do thread
altera prioridade de execução
( 1 - mínima 10 - máxima)
32
Exemplo 1 ( Métodos básicos )
class processos
implements Runnable{
processos(){ // Construtor
Thread principal=Thread.currentThread(); // Pega thread corrente
Thread subordinado=new Thread(this,”subordinado”);//Instancia novo thread
System.out.println(“Thread subordinado=“+subordinado);
subordinado.start(); //Inicia execução do thread subordinado
}
public void run(){ // Método de execução dos threads
try{
for(int i=0;i<20;i++){
System.out.println(“i=“+i);
Thread.sleep(1000); // Deixa thread dormindo durante 1 segundo
}
}
catch(InterruptedException e){ // Recuperação da exceção de interrupção do thread
System.out.println(“Thread interromprido”);
}
}
}
33
Exemplo 2 ( Prioridades )
class prioridade
implements Runnable{
int vezes=0;
// Contador de execuções
private Thread atual;
private boolean executando=true;
public prioridade(int prio){ // Construtor
atual=new Thread(this);
atual.setPriority(prio); // Altera prioridade do Thread
}
public void run() { // Método de execução
while(executando)
vezes++;
}
public void stop(){ // Método de parada do thread
executando=false;
}
public void start(){ // Método de início do thread
atual.start();
}
}
34
Exemplo 2 ( Continuação )
class testeprioridade{
public static void main(String args[]){
Thread.currentThread().setPriority(Thread.MAX_PRIORITY); // Prioridade 10 para thread corrente
prioridade alta=new prioridade(Thread.NORM_PRIORITY+2); // Prioridade 7
prioridade baixa= new prioridade(Thread.NORM_PRIORITY-2); // Prioridade 3
baixa.start(); // Coloca primeiro o de baixa prioridade na fila de processos
alta.start();
try{
Thread.sleep(10000); // Faz thread corrente dormir por 10 segundos
}
catch(InterruptedException e){...}
baixa.stop();
alta.stop();
}
}
35
Threads concorrentes
Threads podem também acessar recursos
concorrentemente, como por exemplo,
chamar o método System.out.println.
Se um thread utiliza algum método que possa
fazer acesso concorrente, há necessidade de
sincronizar tal método.
36
Exemplo 1 ( Sem sincronização)
class concorrente
implements Runnable{
String s;
concorrente(String s){ // Construtor
this.s=s;
new Thread(this).start();
}
void imprime(){ // Imprime a string do objeto
System.out.print(“[“+s);
try Thread.sleep(1000); // Coloca Thread para dormir durante 1 segundo
catch(InterruptedException e){ ...};
System.out.println(“]”);
}
public void run(){ // Método de execução dos threads
imprime();
}
}
37
Exemplo 1 ( continuação)
class exemplo{
public static void main(String args[]){
new concorrente(“Oia”);
new concorrente(“nóis aqui”);
new concorrente(“traveis.”);
}
}
O resultado desta execução seria algo do tipo:
[Oia[nóis aqui[traveis.]
]
]
38
Solução do problema de concorrência
do exemplo 1
A origem do problema do do exemplo 1 está
no acesso concorrente à System.out, uma
vez que os threads foram “dormir” sem
acabar de produzir toda a saída.
A solução para isto é definir o método
imprimir sincronizado.
synchronized void imprime();
39
Comunicação entre threads
Em Java, threads podem se comunicar através dos seguintes
métodos:
 wait()
throws
InterruptedException,
IllegalMonitorStateException: indica ao thread que ele
deve desistir de um recursos até que seja notificado por
outro thread.
 notify() throws IllegalMonitorStateException: torna
pronto o primeiro thread que chamou wait() para o recurso.
 notifyAll() throws IllegalMonitorStateException: torna
prontos todos os thread que chamaram wait() para o
recurso.
40
Exemplo ( Definição do recurso )
class recurso{
int n; // Recurso é uma variávei inteira
boolean produziu=false;
// Se não alterou variáveil n, fica false
synchronized int le(){ // lê valor de n
if(!produziu) // Se n não foi alterada
try wait(); // Espera produzir
catch(InterruptedException e){...}
catch(IllegalMonitorException e){...}
produziu=false;
notify();
return(n);
}
synchronized void altera(int n){ // Altera valor de n
if(produziu) // Alteração colocada anteriormente, porém ainda não lida
try wait();
catch(InterruptedException e){...}
catch(IllegalMonitorException e){...}
this.n=n;
produziu=true;
notify();
}
}
41
Exemplo ( thread produtor)
class produtor
implements Runnable{
recurso r;
produtor(recurso r){ // Construtor do produtor
this.r=r;
(new Thread(this,”PRODUTOR”)).start();
}
public void run(){
int n=0;
while(true)
r.altera(n);
}
}
42
Exemplo ( thread consumidor)
class consumidor
implements Runnable{
recurso r;
consumidor(recurso r){ // Construtor do consumidor
this.r=r;
(new Thread(this,”CONSUMIDOR”)).start();
}
public void run(){
while(true)
System.out.println(“Lido dado “+r.le());
}
}
43
Exemplo ( utilização do produtor e
consumidor)
class utilizacao{
public static void main(String args[]){
recurso rec=new recurso(); // recurso a ser compartilhado pelo produtor e pelo consumidor
new produtor(rec);
// inicializa produtor com recurso rec
new consumidor(rec);
// inicializa consumidor com recursos rec
}
}
Download