Introduction
Coroutines are Kotlin's approach to writing asynchronous and concurrent code that looks sequential and is easy to reason about. They are lightweight compared to threads, meaning thousands of coroutines can run on just a handful of OS threads. Coroutines are not part of Kotlin's core standard library; they are provided by the kotlinx.coroutines library, which builds on language features like suspend functions.
Cricket analogy: Coroutines are like a stadium running thousands of fan queue-lines through just a handful of ticket gates (OS threads): each queue pauses and resumes at the gate without needing its own dedicated turnstile, unlike heavy dedicated-thread gates.
Syntax
suspend fun fetchData(): String {
// can be paused and resumed without blocking a thread
return "data"
}
CoroutineScope(Dispatchers.IO).launch {
val result = fetchData()
println(result)
}Explanation
A suspend fun marks a function that can be paused and resumed later without blocking the underlying thread. Coroutines are launched inside a CoroutineScope using builders such as launch, which is fire-and-forget and returns a Job, or async, which returns a Deferred<T> whose result is retrieved with .await(). runBlocking bridges regular blocking code with coroutine code and is mainly used in main functions or tests. Dispatchers like Dispatchers.Main, Dispatchers.IO, and Dispatchers.Default determine which thread pool a coroutine actually executes on.
Cricket analogy: A suspend fun reviewing a DRS replay pauses without freezing the whole match; launch is like sending a fielder to fetch water (fire-and-forget, returns a Job), async is like requesting a stat from the analyst you'll collect later via .await(), and Dispatchers.IO decides which support staff handles it.
Example
import kotlinx.coroutines.*
suspend fun fetchUser(): String {
delay(1000L)
return "Alice"
}
suspend fun fetchScore(): Int {
delay(1000L)
return 95
}
fun main() = runBlocking {
val userDeferred = async { fetchUser() }
val scoreDeferred = async { fetchScore() }
println("${userDeferred.await()} scored ${scoreDeferred.await()}")
}
// Output:
// Alice scored 95Key Takeaways
- Coroutines are lightweight; many can run on just a few OS threads.
- suspend fun marks a function that can pause and resume without blocking a thread.
- launch is fire-and-forget; async returns a Deferred<T> retrieved with .await().
- runBlocking bridges blocking code with coroutine code, mainly for main functions and tests.
- Dispatchers (Main, IO, Default) control which thread pool a coroutine runs on.
- Coroutines come from the kotlinx.coroutines library, not the core language.
Practice what you learned
1. What does a suspend function allow a coroutine to do?
2. Which coroutine builder returns a Deferred<T>?
3. What is the primary use case for runBlocking?
4. Where do Kotlin coroutines come from?
5. What determines which thread pool a coroutine runs on?
Was this page helpful?
You May Also Like
Exception Handling in Kotlin
Learn how Kotlin handles runtime errors using try-catch-finally, unchecked exceptions, and try as an expression.
Lambda Expressions in Kotlin
Understand how to write and use lambda expressions in Kotlin, including trailing lambda syntax and the implicit it parameter.
Higher-Order Functions in Kotlin
Learn how Kotlin functions can accept or return other functions, enabling flexible, reusable, functional-style code.
Functions in Kotlin
Learn how to declare, call, and simplify functions in Kotlin, including single-expression syntax and the Unit type.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics