Intermediate 10 min readKotlin 2.0

Kotlin Coroutines — A Beginner-Friendly Introduction

Coroutines make asynchronous programming readable and safe. This beginner guide explains the core concepts with practical examples.

What You Will Learn

  • What a coroutine is and why it helps
  • How to use runBlocking and launch
  • What suspend functions are
  • How delay works without blocking threads
  • Why coroutines are better than callbacks

What is a Coroutine?

A coroutine is a block of code that can suspend its execution without blocking the thread it runs on. Think of it as a lightweight task that can pause when it is waiting (for a network response, a timer, or a database read) and let other work happen in the meantime. Before coroutines, asynchronous Kotlin and Java code relied on callbacks and threads. Callbacks lead to deeply nested code ("callback hell"), and threads are expensive to create and manage. Coroutines solve both problems.

Your First Coroutine

Dependency required: implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        delay(1000)
        println("Coroutine finished")
    }
    println("Main continues")
}
Output
Main continues Coroutine finished

runBlocking creates a coroutine scope and blocks the current thread until all child coroutines finish. launch starts a new coroutine concurrently. delay(1000) suspends the coroutine for 1 second without blocking the thread.

Beginner Tip: runBlocking is mainly used in main functions and tests. In real applications (Android, Ktor), coroutine scopes are managed by the framework.
Dependency required: implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")

suspend Functions

A suspend function is a function that can pause its execution and resume later. Only coroutines (or other suspend functions) can call suspend functions. The suspend keyword tells the Kotlin compiler that this function may suspend.

Writing a suspend Function

kotlin
import kotlinx.coroutines.*

suspend fun fetchData(): String {
    delay(500)  // simulates network request
    return "Data loaded"
}

fun main() = runBlocking {
    val result = fetchData()
    println(result)
}
Output
Data loaded

fetchData is a suspend function. delay inside it suspends the function, freeing the thread. When the delay is done, the function resumes and returns its result.

suspend functions are normal functions at the JVM level. The Kotlin compiler transforms them into state machines behind the scenes.

async and await

Use async when you want to start a coroutine that returns a result. await() suspends the calling coroutine until the result is ready.

async and await Example

Dependency required: implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0")
kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    val result = async {
        delay(500)
        10 + 20
    }
    println(result.await())
}
Output
30

async returns a Deferred<Int>. await() suspends until the async block finishes and returns 30. The computation runs concurrently with other code.

Practice Exercise

Exercisepredict output

What does this print, and in what order? import kotlinx.coroutines.* fun main() = runBlocking { launch { println("B") } println("A") }

Quick Quiz

Quick Quiz

What does delay() do in a Kotlin coroutine?

Frequently Asked Questions

Related Tutorials

Last updated: 2026-05-01Kotlin 2.0

Written by KotlinGuide Editorial Team · Reviewed by KotlinGuide Technical Review