Multithreading

Multithreading, ou multithreaded programming, é uma técnica fundamental na programação moderna. Em Java, multithreading refere-se à capacidade de um programa executar simultaneamente duas ou mais partes do mesmo programa, aproveitando os múltiplos núcleos do processador. Neste artigo, vamos explorar o multithreading em Java, entender como ele funciona e examinar exemplos práticos para ilustrar esses conceitos.

O que é Multithreading?

Multithreading é a capacidade de um CPU (Central Processing Unit) ou um único núcleo de CPU realizar múltiplas tarefas concorrentemente. Isso é particularmente útil para programas que precisam realizar várias operações ao mesmo tempo, como aplicações de servidor, jogos e aplicativos de processamento em lote.

Threads em Java

Em Java, a programação multithreaded é feita usando a classe Thread. Uma thread representa uma sequência independente de execução. Um programa Java pode ter várias threads, cada uma executando partes diferentes do código. As threads em Java são usadas para melhorar o desempenho, realizar operações de entrada/saída de forma assíncrona e criar aplicativos interativos e responsivos.

Criando e Iniciando Threads em Java

Existem duas maneiras principais de criar e iniciar threads em Java:

1. Estendendo a Classe Thread

class MinhaThread extends Thread {
    public void run() {
        System.out.println("Minha thread está executando.");
    }
}

public class ExemploThread {
    public static void main(String[] args) {
        MinhaThread minhaThread = new MinhaThread();
        minhaThread.start(); // Inicia a execução da thread
    }
}

2. Implementando a Interface Runnable

class MinhaRunnable implements Runnable {
    public void run() {
        System.out.println("Minha thread está executando.");
    }
}

public class ExemploRunnable {
    public static void main(String[] args) {
        Thread minhaThread = new Thread(new MinhaRunnable());
        minhaThread.start(); // Inicia a execução da thread
    }
}

Ambos os métodos resultarão na execução assíncrona do método run() nas threads criadas.

Sincronização e Concorrência em Java

Quando várias threads estão trabalhando simultaneamente, podem ocorrer problemas de concorrência, como condições de corrida e leitura/gravação inconsistente. Java oferece mecanismos para evitar esses problemas:

1. Synchronized Keyword

O modificador synchronized pode ser aplicado a métodos ou blocos de código para garantir que apenas uma thread por vez possa executar o código sincronizado.

class Contador {
    private int valor = 0;

    public synchronized void incrementar() {
        valor++;
    }

    public synchronized int getValor() {
        return valor;
    }
}

2. Locks (ReentrantLock)

A interface Lock oferece métodos mais flexíveis para sincronização do que o synchronized keyword.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Contador {
    private int valor = 0;
    private Lock lock = new ReentrantLock();

    public void incrementar() {
        lock.lock();
        try {
            valor++;
        } finally {
            lock.unlock();
        }
    }

    public int getValor() {
        lock.lock();
        try {
            return valor;
        } finally {
            lock.unlock();
        }
    }
}

O multithreading em Java é uma técnica poderosa para melhorar o desempenho e criar aplicativos mais responsivos. Ao entender como criar, iniciar e sincronizar threads, você pode criar programas eficientes que podem tirar proveito dos múltiplos núcleos do processador e fornecer uma melhor experiência ao usuário.