Kotlin Coroutine Builders
Coroutine builders are functions that start a coroutine. Each builder has different behavior for how it runs, what it returns, and whether it blocks the calling thread. The three main builders are runBlocking, launch, and async.
runBlocking — Bridges Blocking and Coroutine Worlds
import kotlinx.coroutines.*
fun main() = runBlocking {
println("Inside runBlocking")
delay(500)
println("Done after 500ms")
}
// runBlocking BLOCKS the main thread until all coroutines inside complete
// Use only for main() functions and tests — not in production coroutine codelaunch — Fire and Forget
fun main() = runBlocking {
val job = launch {
delay(1000)
println("launch coroutine done")
}
println("launch started — returns a Job, not a value")
job.join() // waits for this specific coroutine to finish
println("All done")
}Output:
launch started — returns a Job, not a value
launch coroutine done
All doneasync — Returns a Result
fun main() = runBlocking {
val deferred = async {
delay(800)
"Result from async"
}
println("async started — working in background...")
val result = deferred.await() // suspends here until result is ready
println("Got: $result")
}Output:
async started — working in background...
Got: Result from asynclaunch vs async Side by Side
launch async
────────────────────────────────────────────────────
Returns Job Deferred
Get result? NO YES via .await()
Use when? side effects, when you need the
fire and forget computed result
Parallel Execution with async
suspend fun loadUserName(): String { delay(600); return "Alice" }
suspend fun loadUserScore(): Int { delay(400); return 1850 }
fun main() = runBlocking {
val start = System.currentTimeMillis()
// Sequential: ~1000ms total
// val name = loadUserName()
// val score = loadUserScore()
// Parallel: ~600ms total (both run at same time)
val nameDeferred = async { loadUserName() }
val scoreDeferred = async { loadUserScore() }
val name = nameDeferred.await()
val score = scoreDeferred.await()
println("$name scored $score")
println("Time: ${System.currentTimeMillis() - start}ms")
}Output:
Alice scored 1850
Time: ~620msMultiple launch Jobs
fun main() = runBlocking {
val jobs = List(5) { index ->
launch {
delay((index + 1) * 200L)
println("Job $index complete")
}
}
jobs.forEach { it.join() } // wait for all
println("All jobs finished")
}Output:
Job 0 complete
Job 1 complete
Job 2 complete
Job 3 complete
Job 4 complete
All jobs finishedCancelling a Job
fun main() = runBlocking {
val job = launch {
repeat(10) { i ->
println("Working step $i")
delay(300)
}
}
delay(800) // let it run for a bit
job.cancel() // cancel the coroutine
job.join() // wait for cancellation to complete
println("Job cancelled")
}Output:
Working step 0
Working step 1
Working step 2
Job cancelledPractical Example: Dashboard Loader
suspend fun fetchStats(): String { delay(500); return "Views: 1500, Sales: 320" }
suspend fun fetchAlerts(): String { delay(300); return "2 low-stock alerts" }
suspend fun fetchRevenue(): String { delay(400); return "Revenue: ₹84,000" }
fun main() = runBlocking {
val start = System.currentTimeMillis()
val stats = async { fetchStats() }
val alerts = async { fetchAlerts() }
val revenue = async { fetchRevenue() }
println("=== Dashboard ===")
println(stats.await())
println(alerts.await())
println(revenue.await())
println("Loaded in ${System.currentTimeMillis() - start}ms")
}Output:
=== Dashboard ===
Views: 1500, Sales: 320
2 low-stock alerts
Revenue: ₹84,000
Loaded in ~520ms
