diff --git a/docs/images/coroutines-and-threads.svg b/docs/images/coroutines-and-threads.svg
new file mode 100644
index 0000000000..ed38d9d52b
--- /dev/null
+++ b/docs/images/coroutines-and-threads.svg
@@ -0,0 +1,27 @@
+
diff --git a/docs/images/parallelism-and-concurrency.svg b/docs/images/parallelism-and-concurrency.svg
new file mode 100644
index 0000000000..6e56f96ede
--- /dev/null
+++ b/docs/images/parallelism-and-concurrency.svg
@@ -0,0 +1,42 @@
+
diff --git a/docs/images/run-icon.png b/docs/images/run-icon.png
new file mode 100644
index 0000000000..ebc6d3e91c
Binary files /dev/null and b/docs/images/run-icon.png differ
diff --git a/docs/topics/coroutines-basics.md b/docs/topics/coroutines-basics.md
index 5b467c58bf..ff92c0f472 100644
--- a/docs/topics/coroutines-basics.md
+++ b/docs/topics/coroutines-basics.md
@@ -1,293 +1,499 @@
-
https://github.com/Kotlin/kotlinx.coroutines/edit/master/docs/topics/
[//]: # (title: Coroutines basics)
-This section covers basic coroutine concepts.
+To create applications that perform multiple tasks at once, a concept known as concurrency,
+Kotlin uses coroutines. Coroutines let you write concurrent code in a clear and sequential style.
-## Your first coroutine
+The most basic building block of coroutines is the suspending function.
+It makes it possible to pause a running operation and resume it later without losing the structure of your code.
-A _coroutine_ is an instance of a suspendable computation. It is conceptually similar to a thread, in the sense that it
-takes a block of code to run that works concurrently with the rest of the code.
-However, a coroutine is not bound to any particular thread. It may suspend its execution in one thread and resume in another one.
+To mark a function as suspendable, use the `suspend` keyword:
-Coroutines can be thought of as light-weight threads, but there is a number
-of important differences that make their real-life usage very different from threads.
+```kotlin
+suspend fun greet() {
+ println("Hello world from a suspending function")
+}
+```
-Run the following code to get to your first working coroutine:
+You can only call a suspending function from another suspending function.
+To call suspending functions at the entry point of a Kotlin application, mark the `main()` function as suspendable:
```kotlin
-import kotlinx.coroutines.*
+suspend fun main() {
+ showUserInfo()
+}
-//sampleStart
-fun main() = runBlocking { // this: CoroutineScope
- launch { // launch a new coroutine and continue
- delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
- println("World!") // print after delay
- }
- println("Hello") // main coroutine continues while a previous one is delayed
+suspend fun showUserInfo() {
+ println("Loading user...")
+ greet()
+ println("User: John Smith")
+}
+
+suspend fun greet() {
+ println("Hello world from a suspending function")
}
-//sampleEnd
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt).
->
-{style="note"}
+{kotlin-runnable="true"}
-You will see the following result:
+This example doesn't use concurrency yet, but by marking the functions with the `suspend` keyword,
+you allow them to call other suspending functions and run concurrent code inside.
-```text
-Hello
-World!
-```
+While the `suspend` keyword is part of the core Kotlin language, most coroutine features
+are available through the [`kotlinx.coroutines`](https://github.com/Kotlin/kotlinx.coroutines) library.
-
+## Add the kotlinx.coroutines library to your project
-Let's dissect what this code does.
+To include the `kotlinx.coroutines` library in your project, add the corresponding dependency configuration based on your build tool.
-[launch] is a _coroutine builder_. It launches a new coroutine concurrently with
-the rest of the code, which continues to work independently. That's why `Hello` has been printed first.
+### Gradle
-[delay] is a special _suspending function_. It _suspends_ the coroutine for a specific time. Suspending a coroutine
-does not _block_ the underlying thread, but allows other coroutines to run and use the underlying thread for
-their code.
+Add the following dependency to your `build.gradle(.kts)` file:
-[runBlocking] is also a coroutine builder that bridges the non-coroutine world of a regular `fun main()` and
-the code with coroutines inside of `runBlocking { ... }` curly braces. This is highlighted in an IDE by
-`this: CoroutineScope` hint right after the `runBlocking` opening curly brace.
+
+
-If you remove or forget `runBlocking` in this code, you'll get an error on the [launch] call, since `launch`
-is declared only on the [CoroutineScope]:
+```kotlin
+// build.gradle.kts
+repositories {
+ mavenCentral()
+}
+dependencies {
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:%coroutinesVersion%")
+}
```
-Unresolved reference: launch
+
+
+
+
+```groovy
+// build.gradle
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:%coroutinesVersion%'
+}
+```
+
+
+
+### Maven
+
+Add the following dependency to your `pom.xml` file.
+
+```xml
+
+
+
+ org.jetbrains.kotlin
+ kotlinx-coroutines-core
+ %coroutinesVersion%
+
+
+ ...
+
```
-The name of `runBlocking` means that the thread that runs it (in this case — the main thread) gets _blocked_ for
-the duration of the call, until all the coroutines inside `runBlocking { ... }` complete their execution. You will
-often see `runBlocking` used like that at the very top-level of the application and quite rarely inside the real code,
-as threads are expensive resources and blocking them is inefficient and is often not desired.
+## Create your first coroutines
+
+Suspending functions are the basic building blocks for concurrency in Kotlin.
+A coroutine is a suspendable computation that can run concurrently with other coroutines and potentially in parallel.
-### Structured concurrency
+On the JVM and in Kotlin/Native, all concurrent code, such as coroutines, runs on _threads_, which are managed by the operating system.
+Coroutines can suspend their execution instead of blocking a thread.
+This allows one coroutine to suspend while waiting for a network response and another to run on the same thread, ensuring effective resource utilization.
-Coroutines follow a principle of
-**structured concurrency** which means that new coroutines can only be launched in a specific [CoroutineScope]
-which delimits the lifetime of the coroutine. The above example shows that [runBlocking] establishes the corresponding
-scope and that is why the previous example waits until `World!` is printed after a second's delay and only then exits.
+{width="700"}
-In a real application, you will be launching a lot of coroutines. Structured concurrency ensures that they are not
-lost and do not leak. An outer scope cannot complete until all its children coroutines complete.
-Structured concurrency also ensures that any errors in the code are properly reported and are never lost.
+To create a coroutine in Kotlin, you need the following:
-## Extract function refactoring
+* A suspending function.
+* A coroutine scope in which it can run, such as one available inside the `withContext()` function.
+* A coroutine builder like `.launch()` to start it.
+* A dispatcher to control which threads it uses.
-Let's extract the block of code inside `launch { ... }` into a separate function. When you
-perform "Extract function" refactoring on this code, you get a new function with the `suspend` modifier.
-This is your first _suspending function_. Suspending functions can be used inside coroutines
-just like regular functions, but their additional feature is that they can, in turn,
-use other suspending functions (like `delay` in this example) to _suspend_ execution of a coroutine.
+> You can display coroutine names next to thread names in the output of your code for additional information.
+> To do so, pass the `-Dkotlinx.coroutines.debug` VM option in your build tool or IDE run configuration.
+>
+> See [Debugging coroutines](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/topics/debugging.md) for more information.
+>
+{style="tip"}
+
+Let's look at an example that uses multiple coroutines in a multithreaded environment:
+
+1. Import the `kotlinx.coroutines` library:
+
+ ```kotlin
+ import kotlinx.coroutines.*
+ ```
+
+2. Mark functions that can pause and resume with the `suspend` keyword:
+
+ ```kotlin
+ suspend fun greet() {
+ println("Hello world from a suspending function on thread: ${Thread.currentThread().name}")
+ }
+
+ suspend fun main() {}
+ ```
+
+ > While you can mark the `main()` function as `suspend` in some projects, it may not be possible when integrating with existing code or using a framework.
+ > In that case, check the framework’s documentation to see if it supports calling suspending functions.
+ > If not, use [`runBlocking`](#runblocking) to call them by blocking the current thread.
+ >
+ {style="note"}
+
+
+3. Use [`withContext(Dispatchers.Default)`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html#) to define a safe entry point for multithreaded concurrent code that runs on a shared thread pool:
+
+ ```kotlin
+ suspend fun main() = withContext(Dispatchers.Default) {
+ // Add the coroutine builders here
+ }
+ ```
+
+ > The `withContext()` function is typically used for [context switching](coroutine-context-and-dispatchers.md#jumping-between-threads), but in this example,
+ > it also defines a safe entry point for concurrent code.
+ > It uses the [`Dispatchers.Default` dispatcher](#coroutine-dispatchers) to run code on a shared thread pool for multithreaded execution.
+ >
+ > The coroutines launched inside the `withContext()` block share the same coroutine scope, which ensures [structured concurrency](#coroutine-scope-and-structured-concurrency).
+ >
+ {style="note"}
+
+4. Use a [coroutine builder function](#coroutine-builder-functions) like [`.launch()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html) to start the coroutine:
+
+ ```kotlin
+ suspend fun main() = withContext(Dispatchers.Default) {
+ // Starts a coroutine inside the scope
+ launch { greet() }
+ println("This runs concurrently and possibly in parallel with the launched coroutines on thread: ${Thread.currentThread().name}")
+ }
+ ```
+
+5. Combine these pieces to run multiple coroutines at the same time on a shared pool of threads:
+
+ ```kotlin
+ // Imports the coroutines library
+ import kotlinx.coroutines.*
+
+ // Defines a suspending function
+ suspend fun greet() {
+ println("Hello from greet() on thread: ${Thread.currentThread().name}")
+ }
+
+ // Runs all concurrent code on a shared thread pool
+ suspend fun main() = withContext(Dispatchers.Default) {
+ launch() {
+ greet()
+ }
+
+ // Starts another coroutine
+ launch() {
+ println("Another coroutine on thread: ${Thread.currentThread().name}")
+ }
+
+ println("This runs concurrently and possibly in parallel with the launched coroutines on thread: ${Thread.currentThread().name}")
+ }
+ ```
+ {kotlin-runnable="true"}
+
+This example demonstrates simple multithreading with coroutines on a shared thread pool.
+
+> Try running the example multiple times.
+> You may notice that the output order and thread names may change each time you run the program.
+> This is because the OS decides when threads run and tasks complete.
+>
+{style="tip"}
+
+## Coroutine scope and structured concurrency
+
+When you run many coroutines in an application, you need a way to manage them as a group.
+Kotlin coroutines rely on a principle called _structured concurrency_ to provide this structure.
+
+This principle connects coroutines into a hierarchy of parent and child tasks that share the same lifecycle.
+A parent coroutine waits for its children to complete before finishing.
+If the parent coroutine fails or is canceled, all its child coroutines are canceled too.
+Keeping coroutines connected this way makes cancellation, error handling, and resource cleanup predictable and safe.
+
+> A coroutine’s lifecycle is the period from its start until it completes, fails, or is canceled.
+>
+{style="tip"}
+
+To maintain structured concurrency, new coroutines can only be launched in a [`CoroutineScope`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/) that defines and manages their lifecycle.
+
+[Coroutine builder functions](#coroutine-builder-functions) are extension functions on `CoroutineScope`.
+When you start a coroutine inside another coroutine, it automatically becomes a child of its parent scope.
+The parent coroutine's scope waits for all its children to finish before it completes.
+
+To create a coroutine scope without launching a new coroutine, use the [`coroutineScope()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html) function:
```kotlin
+// Imports the kotlin.time.Duration to express duration in seconds
+import kotlin.time.Duration.Companion.seconds
+
import kotlinx.coroutines.*
-//sampleStart
-fun main() = runBlocking { // this: CoroutineScope
- launch { doWorld() }
- println("Hello")
-}
+suspend fun main() {
+ println("Starting coroutine scope")
+ coroutineScope {
+ launch {
+ delay(1.seconds)
+ println("The first coroutine completed")
+ }
+ launch {
+ delay(2.seconds)
+ println("The second coroutine completed")
+ }
+ }
-// this is your first suspending function
-suspend fun doWorld() {
- delay(1000L)
- println("World!")
+ // Runs only after all children in the coroutineScope have completed
+ println("Coroutine scope completed")
}
-//sampleEnd
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt).
->
-{style="note"}
+{kotlin-runnable="true"}
-
+This example uses the [`delay()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html#) function to show how the coroutine scope waits for its child coroutines to finish.
+You can specify the wait time in milliseconds, so `delay(1000L)` suspends the coroutine for one second without blocking the thread.
-## Scope builder
+> Use [`kotlin.time.Duration`](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.time/-duration/) from the Kotlin standard library to express durations like `delay(1.seconds)` instead of using milliseconds.
+>
+{style="tip"}
-In addition to the coroutine scope provided by different builders, it is possible to declare your own scope using the
-[coroutineScope][_coroutineScope] builder. It creates a coroutine scope and does not complete until all launched children complete.
+## Coroutine builder functions
-[runBlocking] and [coroutineScope][_coroutineScope] builders may look similar because they both wait for their body and all its children to complete.
-The main difference is that the [runBlocking] method _blocks_ the current thread for waiting,
-while [coroutineScope][_coroutineScope] just suspends, releasing the underlying thread for other usages.
-Because of that difference, [runBlocking] is a regular function and [coroutineScope][_coroutineScope] is a suspending function.
+Coroutine builder functions create new coroutines inside an existing [coroutine scope](#coroutine-scope-and-structured-concurrency).
+They require a `CoroutineScope` to run in, either one that is already available,
+or one you create using helper functions such as `coroutineScope()` or [`runBlocking()`](#runblocking).
+Each builder defines how the coroutine starts and how you interact with its result.
-You can use `coroutineScope` from any suspending function.
-For example, you can move the concurrent printing of `Hello` and `World` into a `suspend fun doWorld()` function:
+> The `withContext()` function doesn't create a new scope but provides access to the current one.
+>
+{style="tip"}
+
+### .launch()
+
+The [`.launch()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html#) coroutine builder function starts a new coroutine without blocking the rest of the scope.
+Use `.launch()` to run a task alongside other work when the result isn't needed or you don't want to wait for it:
```kotlin
-import kotlinx.coroutines.*
+// Imports the kotlin.time.Duration to enable expressing duration in milliseconds
+import kotlin.time.Duration.Companion.milliseconds
-//sampleStart
-fun main() = runBlocking {
- doWorld()
-}
+import kotlinx.coroutines.*
-suspend fun doWorld() = coroutineScope { // this: CoroutineScope
+suspend fun main() = coroutineScope {
+ // Starts a coroutine that runs without blocking the scope
launch {
- delay(1000L)
- println("World!")
+ // Delays to simulate background work
+ delay(100.milliseconds)
+ println("Sending notification in background")
}
- println("Hello")
+
+ // Main coroutine continues while a previous one is delayed
+ println("Scope continues")
}
-//sampleEnd
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt).
->
-{style="note"}
+{kotlin-runnable="true"}
+
+After running this example, you can see that the `main()` function isn't blocked by `.launch()` and keeps running other code while the coroutine works in the background.
-This code also prints:
+### .async()
-```text
-Hello
-World!
+Use the [`.async()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html) builder function to start an asynchronous computation that runs alongside other code and returns a result you can access later.
+The result is wrapped in a [`Deferred`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/) object, which you can access by calling the `.await()` function:
+
+```kotlin
+// Imports the kotlin.time.Duration to enable expressing duration in milliseconds
+import kotlin.time.Duration.Companion.milliseconds
+
+import kotlinx.coroutines.*
+
+suspend fun main() = withContext(Dispatchers.Default) {
+ // Starts downloading the first page
+ val firstPage = async {
+ delay(50.milliseconds)
+ "First page"
+ }
+
+ // Starts downloading the second page in parallel
+ val secondPage = async {
+ delay(100.milliseconds)
+ "Second page"
+ }
+
+ // Awaits both results and compares them
+ val pagesAreEqual = firstPage.await() == secondPage.await()
+ println("Pages are equal: $pagesAreEqual")
+}
```
+{kotlin-runnable="true"}
-
+### runBlocking()
-## Scope builder and concurrency
+The [`runBlocking()`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html) coroutine builder function creates coroutine scope and blocks the current [thread](#comparing-coroutines-and-jvm-threads) until
+the coroutines launched in that scope finish.
+Unlike other coroutine builders, `runBlocking()` doesn't use a shared thread pool.
-A [coroutineScope][_coroutineScope] builder can be used inside any suspending function to perform multiple concurrent operations.
-Let's launch two concurrent coroutines inside a `doWorld` suspending function:
+Use `runBlocking()` only when there is no other option to call suspending code from non-suspending code:
```kotlin
+// Imports the kotlin.time.Duration to enable expressing duration in milliseconds
+import kotlin.time.Duration.Companion.milliseconds
+
import kotlinx.coroutines.*
-//sampleStart
-// Sequentially executes doWorld followed by "Done"
-fun main() = runBlocking {
- doWorld()
- println("Done")
+// A third-party interface we cannot change
+interface Repository {
+ fun readItem(): Int
}
-// Concurrently executes both sections
-suspend fun doWorld() = coroutineScope { // this: CoroutineScope
- launch {
- delay(2000L)
- println("World 2")
- }
- launch {
- delay(1000L)
- println("World 1")
+object MyRepository : Repository {
+ override fun readItem(): Int {
+ // Bridges to a suspending function safely
+ return runBlocking {
+ myReadItem()
+ }
}
- println("Hello")
}
-//sampleEnd
+
+suspend fun myReadItem(): Int {
+ delay(100.milliseconds)
+ return 4
+}
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt).
+
+## Coroutine dispatchers
+
+A [coroutine dispatcher](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/#) controls which thread or thread pool coroutines use for their execution.
+Coroutines aren't always tied to a single thread.
+They can pause on one thread and resume on another, depending on the dispatcher.
+This lets you run many coroutines at the same time without allocating a separate thread for every coroutine.
+
+A dispatcher works together with the [coroutine scope](#coroutine-scope-and-structured-concurrency) to define when coroutines run and where they run.
+While the coroutine scope controls the coroutine's lifecycle, the dispatcher controls which threads are used for execution.
+
+> You don't have to specify a dispatcher for every coroutine.
+> By default, coroutines inherit the dispatcher from their parent scope.
+> You can specify a dispatcher if you need to run a coroutine in a different context.
>
{style="note"}
-Both pieces of code inside `launch { ... }` blocks execute _concurrently_, with
-`World 1` printed first, after a second from start, and `World 2` printed next, after two seconds from start.
-A [coroutineScope][_coroutineScope] in `doWorld` completes only after both are complete, so `doWorld` returns and
-allows `Done` string to be printed only after that:
+The `kotlinx.coroutines` library includes different dispatchers for different use cases.
+For example, [`Dispatchers.Default`](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-default.html) runs coroutines on a shared pool of threads performing work in the background,
+separate from the main thread.
-```text
-Hello
-World 1
-World 2
-Done
-```
+To specify a dispatcher for a coroutine builder like `.launch()`, pass it as an argument:
-
+```kotlin
+suspend fun runWithDispatcher() = coroutineScope {
+ launch(Dispatchers.Default) {
+ println("Running on ${Thread.currentThread().name}")
+ }
+}
+```
-## An explicit job
+Alternatively, you can wrap multiple coroutines in a `withContext()` block to apply a dispatcher to all of them.
-A [launch] coroutine builder returns a [Job] object that is a handle to the launched coroutine and can be
-used to wait for its completion explicitly.
-For example, you can wait for the completion of the child coroutine and then print the "Done" string:
+The following example runs on `Dispatchers.Default`, which is optimized for CPU-intensive operations like data processing:
```kotlin
+// Imports the kotlin.time.Duration to enable expressing duration in milliseconds
+import kotlin.time.Duration.Companion.milliseconds
+
import kotlinx.coroutines.*
-fun main() = runBlocking {
-//sampleStart
- val job = launch { // launch a new coroutine and keep a reference to its Job
- delay(1000L)
- println("World!")
- }
- println("Hello")
- job.join() // wait until child coroutine completes
- println("Done")
-//sampleEnd
+suspend fun main() = withContext(Dispatchers.Default) {
+ println("Running withContext block on ${Thread.currentThread().name}")
+
+ val one = async {
+ println("First calculation starting on ${Thread.currentThread().name}")
+ val sum = (1..500_000).sum()
+ delay(200L)
+ println("First calculation done on ${Thread.currentThread().name}")
+ sum
+ }
+
+ val two = async {
+ println("Second calculation starting on ${Thread.currentThread().name}")
+ val sum = (500_001..1_000_000).sum()
+ println("Second calculation done on ${Thread.currentThread().name}")
+ sum
+ }
+
+ // Waits for both calculations and prints the result
+ println("Combined total: ${one.await() + two.await()}")
}
```
-{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt).
->
-{style="note"}
+{kotlin-runnable="true"}
-This code produces:
+> Even though coroutines can suspend and resume on different threads,
+> values written before the coroutine suspends are still available within the same coroutine when it resumes.
+>
+{style="tip"}
-```text
-Hello
-World!
-Done
-```
+For more information, see [Coroutine context and dispatchers](coroutine-context-and-dispatchers.md)
+
+## Comparing coroutines and JVM threads
+
+While coroutines are suspendable computations that run code concurrently like threads on the JVM, they work differently under the hood.
+
+A _thread_ is managed by the operating system. Threads can run tasks parallel on multiple CPU cores and represent a standard approach to concurrency on the JVM.
+When you create a thread, the operating system allocates memory for its stack and uses the kernel to switch between threads.
+This makes threads powerful but also resource-intensive.
+Each thread usually needs a few megabytes of memory, and typically the JVM can only handle a few thousand threads at once.
-
+On the other hand, a coroutine isn't bound to a specific thread.
+It can suspend on one thread and resume on another, so many coroutines can share the same thread pool.
+When a coroutine suspends, the thread isn't blocked, and it remains free to run other tasks.
+This makes coroutines much lighter than threads and allows running hundreds of thousands in one process without exhausting system resources.
-## Coroutines are light-weight
+{width="700"}
-Coroutines are less resource-intensive than JVM threads. Code that exhausts the
-JVM's available memory when using threads can be expressed using coroutines
-without hitting resource limits. For example, the following code launches
-50,000 distinct coroutines that each waits 5 seconds and then prints a period
-('.') while consuming very little memory:
+Let's look at an example where 50,000 coroutines each wait five seconds and then print a period (`.`):
```kotlin
+// Imports the kotlin.time.Duration to express duration in seconds
+import kotlin.time.Duration.Companion.seconds
+
import kotlinx.coroutines.*
-fun main() = runBlocking {
- repeat(50_000) { // launch a lot of coroutines
+suspend fun main() = coroutineScope {
+ // Launches 50,000 coroutines that each wait five seconds, then print a period
+ repeat(50_000) {
launch {
- delay(5000L)
+ delay(5.seconds)
print(".")
}
}
}
```
{kotlin-runnable="true" kotlin-min-compiler-version="1.3"}
-
-> You can get the full code [here](https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt).
->
-{style="note"}
-
+Now let's look at the same example using JVM threads:
-If you write the same program using threads (remove `runBlocking`, replace
-`launch` with `thread`, and replace `delay` with `Thread.sleep`), it will
-consume a lot of memory. Depending on your operating system, JDK version,
-and its settings, it will either throw an out-of-memory error or start threads slowly
-so that there are never too many concurrently running threads.
+```kotlin
+import kotlin.concurrent.thread
+
+fun main() {
+ repeat(50_000) {
+ thread {
+ Thread.sleep(5000L)
+ print(".")
+ }
+ }
+}
+```
-
-
+Running this version uses much more memory because each thread needs its own memory stack.
+Depending on your operating system, JDK version, and settings,
+it may either throw an out-of-memory error or slow down thread creation to avoid running too many threads at once.
-[launch]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
-[delay]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
-[runBlocking]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
-[CoroutineScope]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
-[_coroutineScope]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
-[Job]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
+## What's next
-
+* Discover more about combining suspending functions in [Composing suspending functions](composing-suspending-functions.md).
+* Learn how to cancel coroutines and handle timeouts in [Cancellation and timeouts](cancellation-and-timeouts.md).
+* Dive deeper into coroutine execution and thread management in [Coroutine context and dispatchers](coroutine-context-and-dispatchers.md).
+* Learn how to return multiple asynchronously computed values in [Asynchronous flows](flow.md)