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.