Skip to content
Lesson 1 of 7

Step 1 of 5 · Reading · ~2 min

Learn

Coroutines

Coroutines are Kotlin's lightweight async primitive. Cooperative, structured, and orders of magnitude cheaper than threads.

A coroutine is suspended with suspend functions:

import kotlinx.coroutines.*

suspend fun fetchUser(id: Int): User {
    delay(100)         // suspend, doesn't block thread
    return database.getUser(id)
}

suspend functions can only be called from other suspend functions, OR from a coroutine builder that creates a scope.

Builders:

  • runBlocking { ... } — bridges blocking and coroutine code (use only in main / tests)
  • launch { ... } — fire-and-forget, returns a Job
  • async { ... } — returns Deferred<T> (like Promise)
  • withContext(ctx) { ... } — switch dispatcher mid-coroutine
fun main() = runBlocking {
    val user = async { fetchUser(1) }
    val settings = async { fetchSettings(1) }

    println("${user.await()} : ${settings.await()}")
}

Both fetches run in parallel. await() yields until ready.

Dispatchers decide what thread runs the coroutine:

  • Dispatchers.Default — CPU-bound work; pool sized to cores
  • Dispatchers.IO — blocking I/O; pool sized larger
  • Dispatchers.Main — UI thread (Android/Swing/JavaFX)
  • Dispatchers.Unconfined — runs on whatever thread suspended (use rarely)

Structured concurrency — coroutines launched in a scope are automatically cancelled if the scope ends. No leaked tasks.

coroutineScope {
    launch { task1() }
    launch { task2() }
    // both finish before this block returns
    // if either fails, both are cancelled
}

This is Kotlin's killer feature over Java's CompletableFuture: cancellation propagation.

What this grader actually has

Everything above is real Kotlin, but kotlinx.coroutines is a separate library, not part of the language or the standard library. This platform's Kotlin grader ships the stdlib only, so import kotlinx.coroutines.* fails here with unresolved reference: kotlinx, and runBlocking, launch, async and delay are unavailable with it.

suspend itself is a language feature and does compile. The stdlib's kotlin.coroutines package gives you the low-level machinery the library is built on:

import kotlin.coroutines.Continuation
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.startCoroutine

suspend fun answer(): Int = 42

fun main() {
    var out: Int? = null
    val block: suspend () -> Int = { answer() }
    block.startCoroutine(Continuation(EmptyCoroutineContext) { r -> out = r.getOrThrow() })
    println(out)          // 42
}

That is what runBlocking is underneath, minus the event loop that makes delay and real parallelism work. Use it for the exercise; use kotlinx.coroutines in a project where you can add the dependency.

Up nextChannels and FlowCoroutines

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…