Threads em Java
Threads em Java
Threads em Java
Conceitos:
Diferença entre processo e thread:
Um processo é um programa em execução que possui o seu próprio espaço de endereçamento.
Um sistema operacional multitarefa é capaz de controlar a execução de mais de um processo
ao mesmo tempo, de forma concorrente, fazendo a CPU alternar a execução das instruções de
cada processo.
A classe java.lang.Thread:
A Máquina Virtual Java permite que uma aplicação tenha diversas linhas de execução rodando
concorrentemente. Há sempre pelo menos uma thread, que roda o método main(). Essa
thread é criada automaticamente, e outras podem ser criadas pelo programador.
Em Java, cada thread é implementada como um objeto, que deve ser uma instância de uma
subclasse de java.lang.Thread criada para esse fim. Os comandos a serem executados em
cada linha de execução serão sempre os comandos de um método de nome public void
run(). A classe Thread implementa a interface Runnable, que obriga a ter o método run().
Ex:
class MinhaThread extends Thread{
public void run(){
<instruções da thread>
}
}
A partir daí é possível criar quantas instâncias se desejar dessa classe. Cada vez que
enviar a mensagem start() para uma instância, uma nova linha de execução será iniciada
com os comandos do método run(), que rodará em paralelo com as outras threads:
ou, simplesmente:
new MinhaThread().start();
Note que não se pode enviar a mensagem run() diretamente para um objeto Thread.
Envia-se a mensagem start(), que criará a thread onde rodarão os comandos do método
run().
Obs: Threads podem ser criadas sem referência explícita, como na forma mais simples
acima ( ex: new MinhaThread().start();) , sem risco de serem removidas pelo Garbage
Collector (coletor de lixo da memória), pois possuem uma referência interna que
permanece até o método run() associado terminar.
O efeito disso é a criação de uma instância de Thread que executará o método run()
definido na classe do argumento do construtor.
Enviando a seguir a mensagem start() para essa thread fará iniciar uma nova linha de
execução com os comandos do método run() da classe X, que rodará em paralelo com as
outras threads.
t.start();
Nome da thread:
Toda thread tem um nome (uma string) para poder ser identificada. O nome pode ser passado
como um parâmetro do construtor, e pode ser recuperado enviando para a thread a
mensagem getName(). Se um nome não for especificado no construtor, um novo nome será
gerado automaticamente para a thread.
Prioridade:
Cada thread possui uma prioridade. Threads com prioridades mais elevadas são executadas
preferencialmente antes de threads com menor prioridade. A prioridade default é 5 (em uma
escala de 1 a 10), mas pode ser alterada enviando a mensagem setPriority(int) para a
thread. (Nota: na classe Thread existem as constantes static MAX_PRIORITY, MIN_PRIORITY e
NORM_PRIORITY, com valores 10, 0 e 5, mas que podem variar dependendo da
implementação).
Quando existem diversas threads de mesma prioridade sendo executadas, Java aloca um
tempo máximo para processar os comandos de cada uma, após o que interrompe a thread em
execução e passa a processar os comandos da seguinte.
O método de classe Thread.currentThread():
Esse método permite acessar a thread que está executando no momento em que é chamado.
É usado dentro do método run() para permitir identificar e/ou alterar os parâmetros da thread
(lembre-se que o run() pode ser de outra classe). Por exemplo, para imprimir o nome da
thread onde esse comando está executando:
System.out.println(Thread.currentThread().getName());
Deve ser usado dentro de um bloco try porque, caso a thread receba uma mensagem
interrupt() enquanto estiver parada por um sleep(), será lançada uma
InterruptedException.
Exemplos:
1. Duas threads com igual prioridade. Cada uma imprime os 100 primeiros inteiros seguidos
da frase TERMINOU Flamengo! ou TERMINOU Botafogo! Uma thread se chama Flamengo,
e a outra, Botafogo. Após cada linha impressa, a thread "dorme" um número aleatório de
milissegundos (entre 0 e 399) para evitar que o laço de impressão termine antes de se
esgotar a fatia de tempo da thread. O nome é dado pelo argumento passado ao construtor
da thread. O método getName() da classe Thread retorna a string com o nome:
2. Uso do método yield(). Força passar o controle para a próxima thread que está esperando.
// adaptado do livro 'Thinking in Java, 3rd ed.' (c) Bruce Eckel 2002
// Uso de yield() em threads.
// No metodo run() o uso de "else yield()" faz com que cada thread
// passe a vez para a proxima thread a cada volta do laco while.
public class YieldingThread extends Thread {
private int contagem = 5; //campo interno de cada thread
public YieldingThread() {
super("" + numeroDaThread); // o nome da thread eh o seu numero
numeroDaThread++;
start();
}
t1.start();
t2.start();
t3.start();
}
}
Referências:
Sun Java Tutorial – parte dedicada a Threads e processos concorrentes:
Concurrency: http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html