In Kotlin, use async to start concurrent work inside a coroutine scope, then call await() to get each result.
Basic example:
import kotlinx.coroutines.*
suspend fun fetchUser(): String {
delay(1000)
return "User"
}
suspend fun fetchPosts(): List<String> {
delay(1000)
return listOf("Post 1", "Post 2")
}
fun main() = runBlocking {
val userDeferred = async {
fetchUser()
}
val postsDeferred = async {
fetchPosts()
}
val user = userDeferred.await()
val posts = postsDeferred.await()
println(user)
println(posts)
}
Here, fetchUser() and fetchPosts() run in parallel. Since both delay for 1 second, the total time is about 1 second instead of 2.
You can also await multiple results with awaitAll:
import kotlinx.coroutines.*
fun main() = runBlocking {
val deferredResults = listOf(
async {
delay(1000)
"Result 1"
},
async {
delay(1000)
"Result 2"
},
async {
delay(1000)
"Result 3"
}
)
val results = deferredResults.awaitAll()
println(results)
}
Output:
[Result 1, Result 2, Result 3]
A common pattern is:
coroutineScope {
val a = async { doWorkA() }
val b = async { doWorkB() }
val resultA = a.await()
val resultB = b.await()
combine(resultA, resultB)
}
For example:
import kotlinx.coroutines.*
suspend fun loadName(): String {
delay(500)
return "Alice"
}
suspend fun loadAge(): Int {
delay(500)
return 30
}
suspend fun loadProfile(): String = coroutineScope {
val name = async { loadName() }
val age = async { loadAge() }
"${name.await()} is ${age.await()} years old"
}
fun main() = runBlocking {
println(loadProfile())
}
Important notes:
asyncreturns aDeferred<T>.await()suspends until the result is ready.asyncshould usually be called insidecoroutineScope,supervisorScope,runBlocking, or another coroutine.- If one
asyncchild fails insidecoroutineScope, the whole scope is cancelled. - Use
asyncfor concurrent computations that return values. - Use
launchfor concurrent work that does not return a value.
If you are doing blocking I/O, use an appropriate dispatcher:
val data = async(Dispatchers.IO) {
blockingNetworkCall()
}
For CPU-heavy work:
val result = async(Dispatchers.Default) {
heavyCalculation()
}
