Multithreading em Java Explicado: Conceitos, Ciclo de Vida e Exemplos Práticos de Código
Aplicações Java frequentemente precisam executar múltiplas tarefas simultaneamente. Este tutorial percorre execução single-threaded vs multi-threaded, ciclo de vida de thread, técnicas de sincronização e exemplos práticos de código ilustrando cada conceito.
O que é Single Thread?
Single thread em Java é menor unidade de execução. Runtime Java cria user thread quando aplicação inicia, e pode adicionar threads de usuário ou daemon threads conforme necessário. Daemon threads rodam em background e não impedem JVM de sair.
Exemplo de single thread:
package demoteste;
public class GuruThread {
public static void main(String[] args) {
System.out.println("Single Thread");
}
}
Vantagens de execução single-threaded:
- Overhead mínimo – apenas um contexto de execução mantido.
- Debugging e manutenção simplificados.
O que é Multithreading em Java?
Multithreading permite duas ou mais threads rodarem concorrentemente, maximizando utilização de CPU. Threads compartilham mesmo espaço de memória, então context switches são rápidos e uso de memória permanece baixo.
Exemplo criando duas threads concorrentes:
package demoteste;
public class GuruThread1 implements Runnable {
public static void main(String[] args) {
Thread guruThread1 = new Thread("Guru1");
Thread guruThread2 = new Thread("Guru2");
guruThread1.start();
guruThread2.start();
System.out.println("Nomes das threads são:");
System.out.println(guruThread1.getName());
System.out.println(guruThread2.getName());
}
@Override
public void run() {
// Lógica da thread vai aqui
}
}
Benefícios do multithreading:
- UI não-bloqueante e processamento em background.
- Resiliência – exceção em uma thread não para outras.
Ciclo de Vida de Thread em Java
Ciclo de vida consiste em cinco estados distintos:
- New – Thread instanciada mas não iniciada.
- Runnable – Thread iniciada e pronta para execução.
- Running – Thread executando ativamente.
- Waiting – Thread suspensa até evento específico ocorrer.
- Dead – Thread finalizou execução.
Principais Métodos de Thread
| Método | Descrição |
|---|---|
| start() | Inicia execução da thread; JVM chama run(). |
| sleep(long millis) | Pausa thread atual pela duração especificada. |
| getName() | Retorna nome da thread. |
| setPriority(int novaPrioridade) | Ajusta prioridade da thread (1-10). |
| yield() | Sugere ao scheduler pausar thread atual. |
Exemplo Prático de Thread
Abaixo exemplo conciso demonstrando criação de thread, ajuste de prioridade e sleep.
package demoteste;
public class ThreadExemplo1 implements Runnable {
@Override
public void run() {
// Trabalho da thread aqui
}
public static void main(String[] args) {
Thread guruThread1 = new Thread();
guruThread1.start();
try {
Thread.sleep(1000); // pausa 1 segundo
} catch (InterruptedException e) {
e.printStackTrace();
}
guruThread1.setPriority(1);
System.out.println(guruThread1.getPriority());
System.out.println("Thread Rodando");
}
}
Exemplo de saída:
Sincronização de Threads
Quando múltiplas threads acessam recursos compartilhados, sincronização garante consistência de dados. Em Java, pode envolver seções críticas com palavra-chave synchronized, garantindo acesso exclusivo.
synchronized(objeto) {
// bloco sincronizado
}
Exemplo Avançado de Multithreading
Abaixo exemplo mais elaborado criando duas threads, cada uma imprimindo nome e contador com delay de um segundo.
package demoteste;
public class GuruThread2 {
public static void main(String[] args) {
GuruThread3 threadGuru1 = new GuruThread3("guru1");
threadGuru1.start();
GuruThread3 threadGuru2 = new GuruThread3("guru2");
threadGuru2.start();
}
}
class GuruThread3 implements Runnable {
private Thread guruthread;
private String guruname;
GuruThread3(String name) {
this.guruname = name;
}
@Override
public void run() {
System.out.println("Thread rodando " + guruname);
for (int i = 0; i < 4; i++) {
System.out.println(i);
System.out.println(guruname);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread foi interrompida");
}
}
}
public void start() {
System.out.println("Thread iniciada");
if (guruthread == null) {
guruthread = new Thread(this, guruname);
guruthread.start();
}
}
}
Saída típica (ilustrada na imagem):
Conclusão
- Multithreading liberta aplicação de chamadas bloqueantes e habilita operações concorrentes.
- Ciclo de vida da thread – New, Runnable, Running, Waiting, Dead – define estados pelos quais thread passa.
- Sincronização é essencial quando threads compartilham dados, prevenindo race conditions.
- Exemplos práticos de código reforçam entendimento de criação de thread, gerenciamento de ciclo de vida e sincronização.
Java
- Java Hello World: Seu Primeiro Programa
- Funções em C++ Explicadas com Exemplos Práticos de Código
- Dominando Collections em C#: Tutorial Prático com Exemplos do Mundo Real
- Dominando Java String.indexOf(): Localizando Substrings e Exemplos Práticos
- Entendendo Java String.charAt(): Sintaxe, Tipo de Retorno, Exceções e Exemplo Prático
- Dominando o Método compareTo() do Java String: Sintaxe, Casos de Uso e Exemplos Práticos
- Sobrecarga de Construtores em Java – Explicado com Exemplos Práticos de Código
- Programa Java para Determinar se um Número é Primo
- Algoritmo Insertion Sort em Java: Exemplo Claro e Guia Passo a Passo
- Selection Sort em Java: Exemplo Passo a Passo e Código Completo