1<!--- TEST_NAME BasicsGuideTest --> 2 3[//]: # (title: Coroutines basics) 4 5This section covers basic coroutine concepts. 6 7## Your first coroutine 8 9A _coroutine_ is an instance of a suspendable computation. It is conceptually similar to a thread, in the sense that it 10takes a block of code to run that works concurrently with the rest of the code. 11However, a coroutine is not bound to any particular thread. It may suspend its execution in one thread and resume in another one. 12 13Coroutines can be thought of as light-weight threads, but there is a number 14of important differences that make their real-life usage very different from threads. 15 16Run the following code to get to your first working coroutine: 17 18```kotlin 19import kotlinx.coroutines.* 20 21//sampleStart 22fun main() = runBlocking { // this: CoroutineScope 23 launch { // launch a new coroutine and continue 24 delay(1000L) // non-blocking delay for 1 second (default time unit is ms) 25 println("World!") // print after delay 26 } 27 println("Hello") // main coroutine continues while a previous one is delayed 28} 29//sampleEnd 30``` 31{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} 32 33> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-01.kt). 34> 35{type="note"} 36 37You will see the following result: 38 39```text 40Hello 41World! 42``` 43 44<!--- TEST --> 45 46Let's dissect what this code does. 47 48[launch] is a _coroutine builder_. It launches a new coroutine concurrently with 49the rest of the code, which continues to work independently. That's why `Hello` has been printed first. 50 51[delay] is a special _suspending function_. It _suspends_ the coroutine for a specific time. Suspending a coroutine 52does not _block_ the underlying thread, but allows other coroutines to run and use the underlying thread for 53their code. 54 55[runBlocking] is also a coroutine builder that bridges the non-coroutine world of a regular `fun main()` and 56the code with coroutines inside of `runBlocking { ... }` curly braces. This is highlighted in an IDE by 57`this: CoroutineScope` hint right after the `runBlocking` opening curly brace. 58 59If you remove or forget `runBlocking` in this code, you'll get an error on the [launch] call, since `launch` 60is declared only on the [CoroutineScope]: 61 62```Plain Text 63Unresolved reference: launch 64``` 65 66The name of `runBlocking` means that the thread that runs it (in this case — the main thread) gets _blocked_ for 67the duration of the call, until all the coroutines inside `runBlocking { ... }` complete their execution. You will 68often see `runBlocking` used like that at the very top-level of the application and quite rarely inside the real code, 69as threads are expensive resources and blocking them is inefficient and is often not desired. 70 71### Structured concurrency 72 73Coroutines follow a principle of 74**structured concurrency** which means that new coroutines can only be launched in a specific [CoroutineScope] 75which delimits the lifetime of the coroutine. The above example shows that [runBlocking] establishes the corresponding 76scope and that is why the previous example waits until `World!` is printed after a second's delay and only then exits. 77 78In a real application, you will be launching a lot of coroutines. Structured concurrency ensures that they are not 79lost and do not leak. An outer scope cannot complete until all its children coroutines complete. 80Structured concurrency also ensures that any errors in the code are properly reported and are never lost. 81 82## Extract function refactoring 83 84Let's extract the block of code inside `launch { ... }` into a separate function. When you 85perform "Extract function" refactoring on this code, you get a new function with the `suspend` modifier. 86This is your first _suspending function_. Suspending functions can be used inside coroutines 87just like regular functions, but their additional feature is that they can, in turn, 88use other suspending functions (like `delay` in this example) to _suspend_ execution of a coroutine. 89 90```kotlin 91import kotlinx.coroutines.* 92 93//sampleStart 94fun main() = runBlocking { // this: CoroutineScope 95 launch { doWorld() } 96 println("Hello") 97} 98 99// this is your first suspending function 100suspend fun doWorld() { 101 delay(1000L) 102 println("World!") 103} 104//sampleEnd 105``` 106{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} 107 108> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-02.kt). 109> 110{type="note"} 111 112<!--- TEST 113Hello 114World! 115--> 116 117## Scope builder 118 119In addition to the coroutine scope provided by different builders, it is possible to declare your own scope using the 120[coroutineScope][_coroutineScope] builder. It creates a coroutine scope and does not complete until all launched children complete. 121 122[runBlocking] and [coroutineScope][_coroutineScope] builders may look similar because they both wait for their body and all its children to complete. 123The main difference is that the [runBlocking] method _blocks_ the current thread for waiting, 124while [coroutineScope][_coroutineScope] just suspends, releasing the underlying thread for other usages. 125Because of that difference, [runBlocking] is a regular function and [coroutineScope][_coroutineScope] is a suspending function. 126 127You can use `coroutineScope` from any suspending function. 128For example, you can move the concurrent printing of `Hello` and `World` into a `suspend fun doWorld()` function: 129 130```kotlin 131import kotlinx.coroutines.* 132 133//sampleStart 134fun main() = runBlocking { 135 doWorld() 136} 137 138suspend fun doWorld() = coroutineScope { // this: CoroutineScope 139 launch { 140 delay(1000L) 141 println("World!") 142 } 143 println("Hello") 144} 145//sampleEnd 146``` 147{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} 148 149> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-03.kt). 150> 151{type="note"} 152 153This code also prints: 154 155```text 156Hello 157World! 158``` 159 160<!--- TEST --> 161 162## Scope builder and concurrency 163 164A [coroutineScope][_coroutineScope] builder can be used inside any suspending function to perform multiple concurrent operations. 165Let's launch two concurrent coroutines inside a `doWorld` suspending function: 166 167```kotlin 168import kotlinx.coroutines.* 169 170//sampleStart 171// Sequentially executes doWorld followed by "Done" 172fun main() = runBlocking { 173 doWorld() 174 println("Done") 175} 176 177// Concurrently executes both sections 178suspend fun doWorld() = coroutineScope { // this: CoroutineScope 179 launch { 180 delay(2000L) 181 println("World 2") 182 } 183 launch { 184 delay(1000L) 185 println("World 1") 186 } 187 println("Hello") 188} 189//sampleEnd 190``` 191{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} 192 193> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-04.kt). 194> 195{type="note"} 196 197Both pieces of code inside `launch { ... }` blocks execute _concurrently_, with 198`World 1` printed first, after a second from start, and `World 2` printed next, after two seconds from start. 199A [coroutineScope][_coroutineScope] in `doWorld` completes only after both are complete, so `doWorld` returns and 200allows `Done` string to be printed only after that: 201 202```text 203Hello 204World 1 205World 2 206Done 207``` 208 209<!--- TEST --> 210 211## An explicit job 212 213A [launch] coroutine builder returns a [Job] object that is a handle to the launched coroutine and can be 214used to explicitly wait for its completion. For example, you can wait for completion of the child coroutine 215and then print "Done" string: 216 217```kotlin 218import kotlinx.coroutines.* 219 220fun main() = runBlocking { 221//sampleStart 222 val job = launch { // launch a new coroutine and keep a reference to its Job 223 delay(1000L) 224 println("World!") 225 } 226 println("Hello") 227 job.join() // wait until child coroutine completes 228 println("Done") 229//sampleEnd 230} 231``` 232{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} 233 234> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-05.kt). 235> 236{type="note"} 237 238This code produces: 239 240```text 241Hello 242World! 243Done 244``` 245 246<!--- TEST --> 247 248## Coroutines are light-weight 249 250Coroutines are less resource-intensive than JVM threads. Code that exhausts the 251JVM's available memory when using threads can be expressed using coroutines 252without hitting resource limits. For example, the following code launches 25350,000 distinct coroutines that each waits 5 seconds and then prints a period 254('.') while consuming very little memory: 255 256```kotlin 257import kotlinx.coroutines.* 258 259fun main() = runBlocking { 260 repeat(50_000) { // launch a lot of coroutines 261 launch { 262 delay(5000L) 263 print(".") 264 } 265 } 266} 267``` 268{kotlin-runnable="true" kotlin-min-compiler-version="1.3"} 269 270> You can get the full code [here](../../kotlinx-coroutines-core/jvm/test/guide/example-basic-06.kt). 271> 272{type="note"} 273 274<!--- TEST lines.size == 1 && lines[0] == ".".repeat(50_000) --> 275 276If you write the same program using threads (remove `runBlocking`, replace 277`launch` with `thread`, and replace `delay` with `Thread.sleep`), it will 278consume a lot of memory. Depending on your operating system, JDK version, 279and its settings, it will either throw an out-of-memory error or start threads slowly 280so that there are never too many concurrently running threads. 281 282<!--- MODULE kotlinx-coroutines-core --> 283<!--- INDEX kotlinx.coroutines --> 284 285[launch]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html 286[delay]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html 287[runBlocking]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html 288[CoroutineScope]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html 289[_coroutineScope]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html 290[Job]: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html 291 292<!--- END --> 293