kotlinintermediate

Coroutines — launch, async, and Structured Concurrency

Write concurrent code with Kotlin coroutines: launch, async/await, structured concurrency, and dispatchers.

kotlin
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

fun main() = runBlocking {
    // launch — fire and forget
    val job = launch {
        delay(100)
        println("Background task done")
    }
    job.join() // wait for completion

    // async — returns a result
    val deferred = async {
        delay(100)
        42
    }
    println("Result: ${deferred.await()}") // 42

    // Parallel decomposition
    val time = measureTimeMillis {
        val a = async { fetchUser(1) }
        val b = async { fetchUser(2) }
        val c = async { fetchUser(3) }
        println("Users: ${a.await()}, ${b.await()}, ${c.await()}")
    }
    println("Parallel: ${time}ms") // ~200ms, not 600ms

    // Structured concurrency — parent waits for children
    coroutineScope {
        launch { delay(100); println("Child 1") }
        launch { delay(200); println("Child 2") }
        println("Parent waits for children...")
    }
    println("All children done")

    // Dispatcher selection
    withContext(Dispatchers.Default) {
        // CPU-intensive work
        val result = (1..1_000_000).sumOf { it.toLong() }
        println("Sum: $result")
    }

    withContext(Dispatchers.IO) {
        // I/O operations (file, network)
        println("IO operation on ${Thread.currentThread().name}")
    }

    // Cancellation
    val longJob = launch {
        repeat(1000) { i ->
            println("Working $i...")
            delay(100) // cancellable suspension point
        }
    }
    delay(350)
    longJob.cancel()
    longJob.join() // wait for cancellation
    println("Job cancelled")

    // Timeout
    val result = withTimeoutOrNull(500) {
        delay(1000) // takes too long
        "completed"
    }
    println("Timeout result: $result") // null

    // Exception handling
    val handler = CoroutineExceptionHandler { _, ex ->
        println("Caught: ${ex.message}")
    }
    val failJob = launch(handler) {
        throw RuntimeException("Oops!")
    }
    failJob.join()
}

suspend fun fetchUser(id: Int): String {
    delay(200) // simulate network
    return "User-$id"
}

Use Cases

  • Parallel API calls in backend services
  • Non-blocking I/O operations
  • Structured concurrent task management

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.