Ciclo de Vida de um Thread
Introdução
- Examinaremos o que ocorre com um thread ao longo de sua vida com mais atenção
- Uma forma boa de examinar o que ocorre com uma entidade com tempo é de estudar seu
"diagrama de estado"
- Num certo momento, o thread pode estar em um entre vários estados e podemos identificar
os estado e como transições ocorrem entre estados como mostra a figura abaixo
- Esse tipo de diagrama chama-se também "diagrama de estados finito" (porque o
número de estados é finito)

- Esse diagrama não está completo mas mostra as partes essenciais da vida de um thread
- Usaremos o applet Clock para exemplificar conceitos
Criação de um thread
- A aplicação (o browser, por exemplo) chama o método start() do applet quando o
usuário visita a página do applet
- O applet Clock cria um Thread (clockThread) no seu método start():
public void start() {
if (clockThread == null) {
clockThread = new Thread(this, "Clock");
clockThread.start();
}
}
- Depois da execução do statement em destaque o clockThread está no estado "New
Thread"
- Neste momento, temos apenas um objeto thread "vazio"
- Nenhum recurso do sistema foi alocado para o thread
- A única coisa que podemos fazer aqui é iniciar o thread (com start())
- Se chamar qualquer outro método, o resultado será uma IllegalThreadStateException
- Observe que o primeiro argumento do construtor de Thread deve ser um objeto que
implemente a interface Runnable
- Esse é o alvo do thread
- O método run do thread será o método run do alvo (a instância de Clock, neste caso)
- O segundo argumeto é apenas um nome para o thread
Iniciando um thread
- A próxima linha (em destaque abaixo) aloca os recursos necessários para executar um
thread (pilha, etc.), escalona o thread para rodar e chama o método run() do thread que,
neste caso, é o método run da classe Clock
public void start() {
if (clockThread == null) {
clockThread = new Thread(this, "Clock");
clockThread.start();
}
}
- Depois que start() retorna, o thread esté no estado "Runnable"
- Porém, as coisas são um pouco mais complexas
- O thread está "pronto para rodar"
- Se a máquina tiver um único processador, só se poder rodar de verdade um thread de
cada vez
- O sistema Java (JVM) deve implementar um esquema de escalonamento que compartilhe a CPU
entre todos os threads que estão no estado "Runnable"
- Veremos detalhes adiante
- Portanto, um thread que está no estado "Runnable" pode, de fato, estar
esperando a CPU
- Aqui está o método run() da classe Clock
public void run() {
Thread myThread = Thread.currentThread();
while (clockThread == myThread) {
repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// The VM doesn't want us to sleep anymore,
// so get back to work
}
}
}
- Explicaremos melhor o teste do while(clockThread==myThread) quando falarmos como parar
um thread, adiante
- Por enquanto, basta dizer que permite que o thread (e o applet) terminem
- Dentro do loop, o applet chama repaint() que acaba chamando paint() que atualiza o
display
- O método paint segue:
public void paint(Graphics g) {
//get the time and convert it to a date
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
//format it and display it
DateFormat dateFormatter = DateFormat.getTimeInstance();
g.drawString(dateFormatter.format(date), 5, 10);
}
O estado Non-Runnable
- Um thread passa a ser "Non-Runnable" quando um dos seguintes eventos ocorre:
- O método sleep() é chamado
- O thread chama o método wait() que espera por uma condição
- O thread faz um system call "lento" tal como um system call que causa I/O
- Também fala-se que o thread está "bloqueado" esperando algo
- Neste caso, clockThread passa a ser Non-Runnable quando run() chama sleep()
public void run() {
Thread myThread = Thread.currentThread();
while (clockThread == myThread) {
repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// The VM doesn't want us to sleep anymore,
// so get back to work
}
}
}
- Quando o thread está dormindo, ele não roda, mesmo que a CPU esteja livre
- Depois de 1 segundo (1000 milissegundos), o thread para para Runnable novamente e vai
rodar quando "receber" a CPU
- Para cada forma de entrar no estado Non-Runnable, alguma forma específica fará o
thread retornar para o estado Runnable
- Ex.: para retornar de sleep, tempo tem que passar
- Ex.: para retornar de wait, outro objeto vai ter que fazer a condição ocorrer através
de uma chamada a notify()
- Ex.: para retornar de I/O lento, o I/O tem que terminar
- Veremos detalhes adiante quando falarmos de sincronização
de thread
Parando um thread
- Há método stop() para parar um thread mas ele não deve ser usado
- É "deprecated" porque descobriu-se que o método tem problemas (é
"inseguro")
- A outra forma é fazer com que o thread saque que ele tem que parar e retornar do
método run()
- Um exemplo:
public void run() {
int i = 0;
while (i < 100) {
i++;
System.out.println("i = " + i);
}
}
- Este thread morre naturalmente quando o loop termina e retorna-se de run()
- Olhe o método run() de Clock novamente (acima)
- Basta agora escrever o seguinte método do applet
public void stop() { // applets' stop method
clockThread = null;
}
- Quando o applet muda de página, o método stop() do applet é chamado e o thread vai
morrer
- Se você revisitar a página, um novo thread será criado no método start() do applet
Testando o estado de um thread
- Em Java 5, pode-se usar o método Thread.getState que retorna:
- NEW
- RUNNABLE
- BLOCKED
- WAITING
- TIMED_WAITING
- TERMINATED
- Além do mais, pode-se chamar isAlive()
- TRUE significa que o thread está no estado Runnable ou no estado Non-Runnable
programa