Concorrência em Java: Trabalhando com Threads

Conceitos Fundamentais

Em sistemas operacionais, um processo representa uma instância de um programa em execução, enquanto uma thread é a unidade mínima de execução dentro de um processo. Cada processo pode conter múltiplas threads, compartilhando recursos como memória e arquivos.

Concorrência refere-se à execução alternada de tarefas em um mesmo intervalo de tempo — típico em CPUs com apenas um núcleo. Já o paralelismo ocorre quando múltiplas tarefas são executadas simultaneamente, exigindo múltiplos núcleos de CPU.

Para identificar quantos núcleos estão disponíveis no sistema atual:

Runtime runtime = Runtime.getRuntime();
int numCores = runtime.availableProcessors();

Implementação de Threads

Existem duas abordagens principais para criar threads em Java: herança da classe Thread ou implementação da interface Runnable.

Herança da Classe Thread

Quando uma classe estende Thread, ela pode ser tratada como uma thread. O método run() deve ser sobrescrito para definir a lógica da thread.

class Worker extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("Olá! " + this.getName());
            try {
                Thread.sleep(1000); // Pausa por 1 segundo
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt(); // Recupera interrupção
            }
        }
    }
}

É importante destacar que o método run() não inicia uma nova thread por si só. A verdadeira criação da thread acontece através do método start0(), chamado internamente pelo método start().

Implementação da Interface Runnable

A segunda forma é mais recomendada, pois evita restrições de herança múltipla. Ao implementar Runnable, o objeto não é uma thread diretamente, mas pode ser encapsulado por uma thread.

class WorkerTask implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("Saudação: " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Para iniciar essa tarefa como thread:

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

Internamente, a classe Thread utiliza um padrão de proxy estático: ela recebe um objeto Runnable e delega a execução do método run() a ele. Isso permite maior flexibilidade e reuso de código.

Comportamento do Processo

O encerramento da thread principle (main) não implica o fim do processo. O processo só termina quando todas as threads ativas forem finalizadas. Se nenhuma thread for iniciada com start(), o programa pode entrar em bloqueio ou comportamento inesperado.

Tags: java threading Concurrency Multithreading Runnable

Publicado em 9-27 15:28