Guia Completo do Kotlin Coroutines - Combinando Funções Suspensoas

1. Execução Sequencial Padrão --------

Imagine que definimos duas funções suspensas que realizam chamadas a serviços remotos ou cálculos computacionais em diferentes partes do código. Para fins deste exemplo, assumimos que ambas são úteis, embora na prática elas apenas adiem sua execução por um segundo:

suspend fun fetchFirstValue(): Int {
    delay(1000L) // Simulando trabalho útil
    return 13
}

suspend fun fetchSecondValue(): Int {
    delay(1000L) // Simulando trabalho útil
    return 29
}

Se precisamos executá-las em sequência, primeiro chamando fetchFirstValue() e depois fetchSecondValue(), somando seus resultados, faremos isso de forma sequencial normal. Como o código roda dentro de uma corrotina, a ordem de execução é implícita. O exemplo abaixo mede o tempo total para executar ambas as funções suspensas:

runBlocking<Unit> {
    //sampleStart
    val time = measureTimeMillis {
        val first = fetchFirstValue()
        val second = fetchSecondValue()
        println("Resultado final: ${first + second}")
    }
    println("Tempo total: $time ms")
    //sampleEnd
}

A saída será:

The answer is 42
Completed in 2017 ms

2. Execução Concorrente com async -----------

Se fetchFirstValue() e fetchSecondValue() não possuem dependências entre si e desejamos obter os resultados mais rapidammente, podemos executá-las concorrentemente. É exatamente aqui que o async se mostra útil.

Conceitualmente, o async se comprota como o launch. Ambos iniciam uma nova corrotina, que é uma thread leve e executa em paralelo com outras corrotinas. A diferença principal é que launch retorna um Job sem valor associado, enquanto async retorna um Deferred — uma promessa não bloqueante cujo resultado estará disponível posteirormente. Você pode usar .await() para obter o valor final de um Deferred, mas este também é um tipo Job, permitindo que você o cancele se necessário.

runBlocking {
    //sampleStart
    val time = measureTimeMillis {
        val first = async { fetchFirstValue() }
        val second = async { fetchSecondValue() }
        println("Resultado final: ${first.await() + second.await()}")
    }
    println("Tempo total: $time ms")
    //sampleEnd
}

A saída será:

The answer is 42
Completed in 1017 ms

Observe que o tempo foi reduzido pela metade, pois ambas as operações ocorrem em paralelo. Note que, ao utilizar corrotinas, a concorrência sempre deve ser explícita.

Tags: Kotlin coroutines suspend-function async-await Concurrency

Publicado em 8-31 03:18