Concorrência e Multithreading em Kotlin: do Básico ao Avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Concorrência e Multithreading em Kotlin: do Básico ao Avançado



Os aplicativos modernos cada vez mais exigem a execução de várias tarefas simultaneamente. Em Kotlin, assim como em outras linguagens JVM, o multithreading é tradicionalmente implementado através da classe Thread. No entanto, a linguagem oferece uma ferramenta muito mais poderosa e elegante — as corrotinas (coroutines). Neste artigo, abordaremos todos os aspectos de concorrência e multithreading em Kotlin: desde conceitos básicos até técnicas avançadas.



1. Fundamentos do Multithreading: Thread e Runnable



Vamos começar com a abordagem clássica. Em Kotlin, assim como em Java, é possível criar uma thread diretamente:



fun main() {    val thread = Thread {        for (i in 1..5) {            println("Thread: $i")            Thread.sleep(500)        }    }    thread.start()    println("Thread principal finalizada")}


No entanto, o gerenciamento manual de threads tem desvantagens:

  • Alto custo operacional — criar e destruir threads é caro.
  • Complexidade de sincronização — é fácil cometer race condition.
  • Número limitado de threads — o sistema pode criar apenas um número limitado de threads.


Para sincronizar o acesso a dados compartilhados, utiliza-se a palavra-chave synchronized ou bloqueios ReentrantLock:



class Counter {    private var count = 0    @Synchronized    fun increment() {        count++    }}


2. Corrotinas — abordagem moderna para concorrência



Corrotinas são threads leves que resolvem os problemas do multithreading clássico. Elas não estão vinculadas a threads do sistema e podem ser executadas em uma única thread, alternando entre tarefas.



2.1. Primeira corrotina



Para trabalhar com corrotinas, é necessário adicionar a dependência org.jetbrains.kotlinx:kotlinx-coroutines-core. Exemplo de uma corrotina simples:



import kotlinx.coroutines.*

fun main() = runBlocking { launch { delay(1000L) println("Mundo!") } println("Olá,")}


Aqui, runBlocking é a ponte entre o código comum e as corrotinas. launch inicia uma nova corrotina, e delay é o análogo de Thread.sleep(), mas sem bloquear a thread.



2.2. Funções Suspend



A palavra-chave suspend permite pausar a execução de uma função sem bloquear a thread:



suspend fun fetchData(): String {    delay(2000L) // simula uma requisição de rede    return "Dados recebidos"}

fun main() = runBlocking { val result = async { fetchData() } println("Aguardando...") println(result.await())}


2.3. Concorrência estruturada



Kotlin suporta concorrência estruturada — todas as corrotinas filhas são automaticamente concluídas antes da corrotina pai:



fun main() = runBlocking {    coroutineScope {        launch {            delay(1000L)            println("Tarefa 1")        }        launch {            delay(500L)            println("Tarefa 2")        }    }    println("Todas as tarefas concluídas")}


3. Técnicas avançadas: Channel, Flow e Dispatchers



3.1. Canais (Channel)



Canais permitem a troca de dados entre corrotinas. São análogos a uma fila:



fun main() = runBlocking {    val channel = Channel<Int>()        launch {        for (i in 1..5) {            channel.send(i * i)        }        channel.close()    }        for (value in channel) {        println(value)    }}


3.2. Flow — fluxos de dados frios



Flow é um fluxo reativo que emite valores sob demanda:



fun simpleFlow(): Flow<Int> = flow {    for (i in 1..3) {        delay(                

Blogs

Book Recommendations