Introdução à concorrência e multithreading em Kotlin
Os aplicativos modernos exigem cada vez mais a execução de várias tarefas simultaneamente — desde o processamento de requisições de rede até o trabalho com bancos de dados. Na linguagem Kotlin, que é ativamente usada para desenvolvimento Android, aplicações servidoras (Ktor, Spring) e até soluções desktop, existem ferramentas poderosas para trabalhar com concorrência e multithreading.
Neste artigo, vamos abordar os conceitos-chave: threads tradicionais (Threads), corrotinas (Coroutines) — a abordagem moderna para assincronia em Kotlin, bem como mecanismos de sincronização. Você aprenderá quando usar threads e quando usar corrotinas, e receberá exemplos de código prontos.
1. Threads tradicionais (Threads) em Kotlin
Kotlin é totalmente compatível com Java, portanto você pode usar as classes padrão Thread e Runnable. No entanto, Kotlin adiciona açúcar sintático, tornando o código mais conciso.
Criação e inicialização de uma thread
A maneira básica de criar uma thread é passar uma lambda para o construtor Thread:
fun main() { val thread = Thread { println("Thread iniciada: ${Thread.currentThread().name}") for (i in 1..5) { println("Contagem: $i") Thread.sleep(500) } } thread.start() println("Thread principal continua executando") thread.join() // aguarda a conclusão da thread println("Thread principal finalizada")}Neste exemplo, criamos uma thread que imprime números de 1 a 5 com um atraso de 500 ms. O método join() faz com que a thread principal aguarde a conclusão da thread filha.
Problemas com threads
- Alto consumo de recursos — cada thread requer uma pilha de memória separada (geralmente 1 MB).
- Complexidade de sincronização — ao trabalhar com dados compartilhados, é fácil causar uma condição de corrida (race condition).
- Quantidade limitada — em um único dispositivo, não é possível iniciar dezenas de milhares de threads sem perda de desempenho.
É por isso que as corrotinas surgiram em Kotlin — uma alternativa mais leve.
2. Corrotinas (Coroutines) — concorrência moderna em Kotlin
Corrotinas são threads leves que podem suspender sua execução sem bloquear a thread do sistema. Elas são a principal ferramenta para programação assíncrona em Kotlin.
Adicionando corrotinas
Para trabalhar com corrotinas, é necessário adicionar a dependência no build.gradle.kts:
dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0")}Exemplo básico de corrotina
import kotlinx.coroutines.*
fun main() = runBlocking { println("Início do trabalho na thread: ${Thread.currentThread().name}")
launch { // inicia uma nova corrotina delay(1000) // atraso não bloqueante println("Corrotina: ${Thread.currentThread().name}") }
println("Corrotina principal continua executando") delay(2000) // aguarda a conclusão da corrotina filha println("Fim")}Pontos-chave:
runBlocking— ponte entre código comum e corrotinas (bloqueia a thread atual).launch— inicia uma corrotina que não retorna resultado.delay— atraso não bloqueante, ao contrário deThread.sleep().
Async e await para obter resultados
Se a corrotina precisar retornar um valor, use async:
fun main() = runBlocking { val deferred1 = async { delay(1000) "Resultado 1" } val deferred2 = async { delay(500) "Resultado 2" }
println("Aguardando resultados...") val result1 = deferred1.await() val result2