Entendendo Generics no Java
em 14 de Janeiro de 2025
A programação multithreading permite que os aplicativos Java executem várias tarefas simultaneamente, aproveitando melhor os recursos do sistema. Com o suporte robusto do Java para threads e APIs de concorrência, os desenvolvedores podem criar aplicativos eficientes e responsivos.
Neste artigo, exploraremos os conceitos básicos de multithreading, como criar e gerenciar threads, e as ferramentas avançadas que o Java oferece para programação concorrente.
O que é uma Thread?
Uma thread é a menor unidade de execução dentro de um processo. No Java, uma thread permite executar uma tarefa específica de forma independente do fluxo principal do programa.
Criando Threads no Java
Existem duas maneiras principais de criar threads no Java:
Thread
Crie uma classe que estenda Thread
e sobrescreva o método run
.
Exemplo:
class MinhaThread extends Thread {
@Override
public void run() {
System.out.println("Executando na thread: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
MinhaThread thread = new MinhaThread();
thread.start();
}
}
Runnable
Implemente a interface Runnable
e passe-a para um objeto Thread
.
Exemplo:
class MinhaTarefa implements Runnable {
@Override
public void run() {
System.out.println("Executando na thread: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MinhaTarefa());
thread.start();
}
}
Gerenciando Concorrência com a API de Executors
O pacote java.util.concurrent
introduzido no Java 5 fornece ferramentas avançadas para programação multithread. Uma das mais úteis é a API de Executors, que facilita a criação e o gerenciamento de pools de threads.
ExecutorService
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
executor.execute(() -> {
System.out.println("Executando tarefa na thread: " + Thread.currentThread().getName());
});
}
executor.shutdown();
}
}
Sincronização de Threads
Quando várias threads acessam os mesmos recursos, como variáveis compartilhadas, pode ocorrer condições de corrida. Para evitar isso, o Java fornece mecanismos de sincronização.
synchronized
Exemplo:
class Contador {
private int valor = 0;
public synchronized void incrementar() {
valor++;
}
public synchronized int getValor() {
return valor;
}
}
public class Main {
public static void main(String[] args) {
Contador contador = new Contador();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
contador.incrementar();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
contador.incrementar();
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Valor final: " + contador.getValor());
}
}
Ferramentas Avançadas de Concorrência
Além de threads básicas e sincronização, o Java oferece estruturas avançadas para concorrência:
Locks
Os locks do pacote java.util.concurrent.locks
fornecem maior controle sobre o acesso a recursos compartilhados.
ConcurrentHashMap
Uma implementação de mapa thread-safe que evita a necessidade de sincronização manual.
Future
e CompletableFuture
Permitem gerenciar tarefas assíncronas e obter seus resultados no futuro.
A programação multithreading no Java é uma poderosa ferramenta para criar aplicativos eficientes e escaláveis. Com as abordagens básicas e ferramentas avançadas, como Executors e sincronização, os desenvolvedores têm flexibilidade para lidar com tarefas concorrentes de maneira segura e eficaz. Explore as APIs de concorrência para tornar seus projetos mais performáticos e responsivos!