Estevão Dias

3 min de leitura

Threads em Java: do escalonador às Virtual Threads

Estevão Dias

Eu fiz Sistemas Operacionais I com um geologista. Foi há mais de quinze anos. Lembro que ele dizia que precisava reservar hora na biblioteca da UFRJ para usar um computador, que executava um único programa de cada vez, lendo um disquete.

Quando cheguei, os Sistemas Operacionais já estavam aqui. Evoluíram para facilitar que múltiplos programas compartilhassem a mesma máquina.

O primeiro computador que eu usei também foi um da escola, um 486. E eu pude ver o próximo passo na timeline com a chegada dos processadores multicores. Com eles, um componente chamado escalonador/scheduler ganhou protagonismo. Em ptBr, escalonar significa organizar e priorizar. O escalonador coordena as tarefas em execução gerenciando estados como criada, pronta, executando, bloqueada e finalizada.

Com a chegada dos processadores multicores, as threads ganharam protagonismo. Embora já existissem antes, elas permitiram explorar o paralelismo de hardware de forma mais eficiente do que criar múltiplos processos em muitos cenários. Um único processo passou a executar várias tarefas independentes, cada uma representada por uma thread e escalonada separadamente pelo sistema operacional.

Essas tarefas têm tudo a ver com quem programa em Java. São as threads ou “a menor unidade de execução que pode ser escalonada”. Por que unidade de execução e não código? Porque uma tarefa pode ter muito ou pouco código. Demorar ou ser breve. É abstrato, mas se você for curioso como eu e quiser ver esses conceitos na práticas, leia os docs do Completely Fair Scheduler do Linux.

Na Concurrency API do Java, existem diferentes abstrações. As Platform Threads têm uma relação um pra um com as threads do Sistema Operacional. As Virtual Threads são montadas (mounted) em uma Carrier Thread enquanto executam e desmontadas (unmounted) quando bloqueiam em operações suportadas pelo runtime. As Carrier Threads, essas sim, têm relação um pra um com as threads do SO.

O Java 5 trouxe o pacote java.util.concurrent, com abstrações como ExecutorService, Future e a primeira API de concorrência de alto nível do Java. O Java 21 introduziu as Virtual Threads como feature estável, parte do Project Loom. No mesmo release, a Structured Concurrency chegou como preview, ainda em evolução, e Java 26 então…

Thread é um assunto tão fundamental em Java que mesmo um programa com apenas um main já tem uma. A famosa thread main, que aparece na mensagem de erro NullPointerException on thread main. Olhando para o contexto mais amplo, o Garbage Collector também utiliza suas próprias threads, normalmente várias delas, que são Daemon Threads. Daemon Threads não seguram a JVM em execução e, importante, são encerradas abruptamente quando o programa principal termina, sem garantia de completar o trabalho em andamento.

Hardware e Software andam de maos dadas, na minha opinião, quando o problema é entender como as coisas funcionam. Threads são exemplo disso, porque esse contexto histórico que pude ter me ajudou a entendê-las.