blob: 1f772e67fdcdc6a9bdad1f4ed83052d9a4d285bb [file] [log] [blame] [view]
hadihariri7db55532018-09-15 10:35:08 +02001<!--- INCLUDE .*/example-([a-z]+)-([0-9a-z]+)\.kt
2/*
3 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
4 */
5
6// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarov0950dfa2018-07-13 10:33:25 +03007package kotlinx.coroutines.guide.$$1$$2
hadihariri7db55532018-09-15 10:35:08 +02008-->
9<!--- KNIT ../core/kotlinx-coroutines-core/test/guide/.*\.kt -->
10<!--- TEST_OUT ../core/kotlinx-coroutines-core/test/guide/test/BasicsGuideTest.kt
11// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarov0950dfa2018-07-13 10:33:25 +030012package kotlinx.coroutines.guide.test
hadihariri7db55532018-09-15 10:35:08 +020013
14import org.junit.Test
15
16class BasicsGuideTest {
17-->
18
Prendotab8a559d2018-11-30 16:24:23 +030019**Table of contents**
hadihariri7db55532018-09-15 10:35:08 +020020
21<!--- TOC -->
22
23* [Coroutine basics](#coroutine-basics)
24 * [Your first coroutine](#your-first-coroutine)
25 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
26 * [Waiting for a job](#waiting-for-a-job)
27 * [Structured concurrency](#structured-concurrency)
28 * [Scope builder](#scope-builder)
29 * [Extract function refactoring](#extract-function-refactoring)
30 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
31 * [Global coroutines are like daemon threads](#global-coroutines-are-like-daemon-threads)
32
33<!--- END_TOC -->
34
35
36## Coroutine basics
37
38This section covers basic coroutine concepts.
39
40### Your first coroutine
41
42Run the following code:
43
Prendota65e6c8c2018-10-17 11:51:08 +030044<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +030045
hadihariri7db55532018-09-15 10:35:08 +020046```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +030047import kotlinx.coroutines.*
48
49fun main() {
hadihariri7db55532018-09-15 10:35:08 +020050 GlobalScope.launch { // launch new coroutine in background and continue
51 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
52 println("World!") // print after delay
53 }
54 println("Hello,") // main thread continues while coroutine is delayed
55 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
56}
57```
58
Alexander Prendotacbeef102018-09-27 18:42:04 +030059</div>
60
hadihariri7db55532018-09-15 10:35:08 +020061> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-01.kt)
62
Marcin MoskaƂae5bf9ae2018-10-08 09:59:41 +030063You will see the following result:
hadihariri7db55532018-09-15 10:35:08 +020064
65```text
66Hello,
67World!
68```
69
70<!--- TEST -->
71
72Essentially, coroutines are light-weight threads.
73They are launched with [launch] _coroutine builder_ in a context of some [CoroutineScope].
74Here we are launching a new coroutine in the [GlobalScope], meaning that the lifetime of the new
75coroutine is limited only by the lifetime of the whole application.
76
77You can achieve the same result replacing
78`GlobalScope.launch { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
79
80If you start by replacing `GlobalScope.launch` by `thread`, the compiler produces the following error:
81
82```
83Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
84```
85
86That is because [delay] is a special _suspending function_ that does not block a thread, but _suspends_
87coroutine and it can be only used from a coroutine.
88
89### Bridging blocking and non-blocking worlds
90
91The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same code.
Devin Bb104cfc2018-11-12 11:51:00 -050092It is easy to lose track of which one is blocking and which one is not.
hadihariri7db55532018-09-15 10:35:08 +020093Let's be explicit about blocking using [runBlocking] coroutine builder:
94
Prendota65e6c8c2018-10-17 11:51:08 +030095<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +030096
hadihariri7db55532018-09-15 10:35:08 +020097```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +030098import kotlinx.coroutines.*
99
100fun main() {
hadihariri7db55532018-09-15 10:35:08 +0200101 GlobalScope.launch { // launch new coroutine in background and continue
102 delay(1000L)
103 println("World!")
104 }
105 println("Hello,") // main thread continues here immediately
106 runBlocking { // but this expression blocks the main thread
107 delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
108 }
109}
110```
111
Alexander Prendotacbeef102018-09-27 18:42:04 +0300112</div>
113
hadihariri7db55532018-09-15 10:35:08 +0200114> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-02.kt)
115
116<!--- TEST
117Hello,
118World!
119-->
120
121The result is the same, but this code uses only non-blocking [delay].
122The main thread, that invokes `runBlocking`, _blocks_ until the coroutine inside `runBlocking` completes.
123
124This example can be also rewritten in a more idiomatic way, using `runBlocking` to wrap
125the execution of the main function:
126
Prendota65e6c8c2018-10-17 11:51:08 +0300127<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300128
hadihariri7db55532018-09-15 10:35:08 +0200129```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300130import kotlinx.coroutines.*
131
132fun main() = runBlocking<Unit> { // start main coroutine
hadihariri7db55532018-09-15 10:35:08 +0200133 GlobalScope.launch { // launch new coroutine in background and continue
134 delay(1000L)
135 println("World!")
136 }
137 println("Hello,") // main coroutine continues here immediately
138 delay(2000L) // delaying for 2 seconds to keep JVM alive
139}
140```
141
Alexander Prendotacbeef102018-09-27 18:42:04 +0300142</div>
143
hadihariri7db55532018-09-15 10:35:08 +0200144> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt)
145
146<!--- TEST
147Hello,
148World!
149-->
150
151Here `runBlocking<Unit> { ... }` works as an adaptor that is used to start the top-level main coroutine.
152We explicitly specify its `Unit` return type, because a well-formed `main` function in Kotlin has to return `Unit`.
153
154This is also a way to write unit-tests for suspending functions:
Alexander Prendotacbeef102018-09-27 18:42:04 +0300155
Prendota65e6c8c2018-10-17 11:51:08 +0300156<!--- INCLUDE
157import kotlinx.coroutines.*
158-->
159
Alexander Prendotacbeef102018-09-27 18:42:04 +0300160<div class="sample" markdown="1" theme="idea" data-highlight-only>
hadihariri7db55532018-09-15 10:35:08 +0200161
162```kotlin
163class MyTest {
164 @Test
165 fun testMySuspendingFunction() = runBlocking<Unit> {
166 // here we can use suspending functions using any assertion style that we like
167 }
168}
169```
170
Alexander Prendotacbeef102018-09-27 18:42:04 +0300171</div>
172
hadihariri7db55532018-09-15 10:35:08 +0200173<!--- CLEAR -->
174
175### Waiting for a job
176
177Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
178wait (in a non-blocking way) until the background [Job] that we have launched is complete:
179
Prendota65e6c8c2018-10-17 11:51:08 +0300180<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300181
hadihariri7db55532018-09-15 10:35:08 +0200182```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300183import kotlinx.coroutines.*
184
185fun main() = runBlocking {
186//sampleStart
hadihariri7db55532018-09-15 10:35:08 +0200187 val job = GlobalScope.launch { // launch new coroutine and keep a reference to its Job
188 delay(1000L)
189 println("World!")
190 }
191 println("Hello,")
192 job.join() // wait until child coroutine completes
Prendota65e6c8c2018-10-17 11:51:08 +0300193//sampleEnd
hadihariri7db55532018-09-15 10:35:08 +0200194}
195```
196
Alexander Prendotacbeef102018-09-27 18:42:04 +0300197</div>
198
hadihariri7db55532018-09-15 10:35:08 +0200199> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-03.kt)
200
201<!--- TEST
202Hello,
203World!
204-->
205
206Now the result is still the same, but the code of the main coroutine is not tied to the duration of
207the background job in any way. Much better.
208
209### Structured concurrency
210
211There is still something to be desired for practical usage of coroutines.
212When we use `GlobalScope.launch` we create a top-level coroutine. Even though it is light-weight, it still
213consumes some memory resources while it runs. If we forget to keep a reference to the newly launched
214coroutine it still runs. What if the code in the coroutine hangs (for example, we erroneously
215delay for too long), what if we launched too many coroutines and ran out of memory?
216Having to manually keep a reference to all the launched coroutines and [join][Job.join] them is error-prone.
217
218There is a better solution. We can use structured concurrency in our code.
219Instead of launching coroutines in the [GlobalScope], just like we usually do with threads (threads are always global),
220we can launch coroutines in the specific scope of the operation we are performing.
221
222In our example, we have `main` function that is turned into a coroutine using [runBlocking] coroutine builder.
saied89a223f352018-10-30 22:44:20 +0330223Every coroutine builder, including `runBlocking`, adds an instance of [CoroutineScope] to the scope of its code block.
hadihariri7db55532018-09-15 10:35:08 +0200224We can launch coroutines in this scope without having to `join` them explicitly, because
225an outer coroutine (`runBlocking` in our example) does not complete until all the coroutines launched
226in its scope complete. Thus, we can make our example simpler:
227
Prendota65e6c8c2018-10-17 11:51:08 +0300228<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300229
hadihariri7db55532018-09-15 10:35:08 +0200230```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300231import kotlinx.coroutines.*
232
233fun main() = runBlocking { // this: CoroutineScope
hadihariri7db55532018-09-15 10:35:08 +0200234 launch { // launch new coroutine in the scope of runBlocking
235 delay(1000L)
236 println("World!")
237 }
238 println("Hello,")
239}
240```
241
Alexander Prendotacbeef102018-09-27 18:42:04 +0300242</div>
243
hadihariri7db55532018-09-15 10:35:08 +0200244> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-03s.kt)
245
246<!--- TEST
247Hello,
248World!
249-->
250
251### Scope builder
252In addition to the coroutine scope provided by different builders, it is possible to declare your own scope using
253[coroutineScope] builder. It creates new coroutine scope and does not complete until all launched children
254complete. The main difference between [runBlocking] and [coroutineScope] is that the latter does not block the current thread
255while waiting for all children to complete.
256
Prendota65e6c8c2018-10-17 11:51:08 +0300257<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300258
hadihariri7db55532018-09-15 10:35:08 +0200259```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300260import kotlinx.coroutines.*
261
262fun main() = runBlocking { // this: CoroutineScope
hadihariri7db55532018-09-15 10:35:08 +0200263 launch {
264 delay(200L)
265 println("Task from runBlocking")
266 }
267
268 coroutineScope { // Creates a new coroutine scope
269 launch {
270 delay(500L)
271 println("Task from nested launch")
272 }
273
274 delay(100L)
275 println("Task from coroutine scope") // This line will be printed before nested launch
276 }
277
278 println("Coroutine scope is over") // This line is not printed until nested launch completes
279}
280```
281
Alexander Prendotacbeef102018-09-27 18:42:04 +0300282</div>
283
hadihariri7db55532018-09-15 10:35:08 +0200284> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-04.kt)
285
286<!--- TEST
287Task from coroutine scope
288Task from runBlocking
289Task from nested launch
290Coroutine scope is over
291-->
292
293### Extract function refactoring
294
295Let's extract the block of code inside `launch { ... }` into a separate function. When you
296perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
297That is your first _suspending function_. Suspending functions can be used inside coroutines
298just like regular functions, but their additional feature is that they can, in turn,
299use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
300
Prendota65e6c8c2018-10-17 11:51:08 +0300301<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300302
hadihariri7db55532018-09-15 10:35:08 +0200303```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300304import kotlinx.coroutines.*
305
306fun main() = runBlocking {
hadihariri7db55532018-09-15 10:35:08 +0200307 launch { doWorld() }
308 println("Hello,")
309}
310
311// this is your first suspending function
312suspend fun doWorld() {
313 delay(1000L)
314 println("World!")
315}
316```
317
Alexander Prendotacbeef102018-09-27 18:42:04 +0300318</div>
319
hadihariri7db55532018-09-15 10:35:08 +0200320> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-05.kt)
321
322<!--- TEST
323Hello,
324World!
325-->
326
327
328But what if the extracted function contains a coroutine builder which is invoked on the current scope?
329In this case `suspend` modifier on the extracted function is not enough. Making `doWorld` extension
330method on `CoroutineScope` is one of the solutions, but it may not always be applicable as it does not make API clearer.
Vsevolod Tolstopyatovfac516f2018-09-28 14:38:29 +0300331Idiomatic solution is to have either explicit `CoroutineScope` as a field in a class containing target function
332or implicit when outer class implements `CoroutineScope`.
333As a last resort, [CoroutineScope(coroutineContext)][CoroutineScope()] can be used, but such approach is structurally unsafe
334because you no longer have control on the scope this method is executed. Only private API can use this builder.
hadihariri7db55532018-09-15 10:35:08 +0200335
336### Coroutines ARE light-weight
337
338Run the following code:
339
Alexander Prendotacbeef102018-09-27 18:42:04 +0300340<div class="sample" markdown="1" theme="idea" data-highlight-only>
341
hadihariri7db55532018-09-15 10:35:08 +0200342```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300343import kotlinx.coroutines.*
344
345fun main() = runBlocking {
hadihariri7db55532018-09-15 10:35:08 +0200346 repeat(100_000) { // launch a lot of coroutines
347 launch {
348 delay(1000L)
349 print(".")
350 }
351 }
352}
353```
354
Alexander Prendotacbeef102018-09-27 18:42:04 +0300355</div>
356
hadihariri7db55532018-09-15 10:35:08 +0200357> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-06.kt)
358
359<!--- TEST lines.size == 1 && lines[0] == ".".repeat(100_000) -->
360
361It launches 100K coroutines and, after a second, each coroutine prints a dot.
362Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
363
364### Global coroutines are like daemon threads
365
366The following code launches a long-running coroutine in [GlobalScope] that prints "I'm sleeping" twice a second and then
367returns from the main function after some delay:
368
Prendota65e6c8c2018-10-17 11:51:08 +0300369<div class="sample" markdown="1" theme="idea" data-min-compiler-version="1.3">
Alexander Prendotacbeef102018-09-27 18:42:04 +0300370
hadihariri7db55532018-09-15 10:35:08 +0200371```kotlin
Prendota65e6c8c2018-10-17 11:51:08 +0300372import kotlinx.coroutines.*
373
374fun main() = runBlocking {
375//sampleStart
hadihariri7db55532018-09-15 10:35:08 +0200376 GlobalScope.launch {
377 repeat(1000) { i ->
378 println("I'm sleeping $i ...")
379 delay(500L)
380 }
381 }
382 delay(1300L) // just quit after delay
Prendota65e6c8c2018-10-17 11:51:08 +0300383//sampleEnd
hadihariri7db55532018-09-15 10:35:08 +0200384}
385```
386
Alexander Prendotacbeef102018-09-27 18:42:04 +0300387</div>
388
hadihariri7db55532018-09-15 10:35:08 +0200389> You can get full code [here](../core/kotlinx-coroutines-core/test/guide/example-basic-07.kt)
390
391You can run and see that it prints three lines and terminates:
392
393```text
394I'm sleeping 0 ...
395I'm sleeping 1 ...
396I'm sleeping 2 ...
397```
398
399<!--- TEST -->
400
401Active coroutines that were launched in [GlobalScope] do not keep the process alive. They are like daemon threads.
402
Roman Elizarov99c28aa2018-09-23 18:42:36 +0300403<!--- MODULE kotlinx-coroutines-core -->
Roman Elizarov0950dfa2018-07-13 10:33:25 +0300404<!--- INDEX kotlinx.coroutines -->
405[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
406[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
407[GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-global-scope/index.html
408[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
409[runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
410[Job]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html
411[Job.join]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/join.html
412[coroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/coroutine-scope.html
413[CoroutineScope()]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope.html
Roman Elizarov99c28aa2018-09-23 18:42:36 +0300414<!--- END -->
hadihariri7db55532018-09-15 10:35:08 +0200415
416