blob: a9abae6ab487ca97e211dd4350037815e80ed889 [file] [log] [blame] [view]
Roman Elizarov7deefb82017-01-31 10:33:17 +03001# Guide to kotlinx.coroutines by example
2
3This is a short guide on core features of `kotlinx.coroutines` with a series of examples.
4
Roman Elizarov1293ccd2017-02-01 18:49:54 +03005## Table of contents
6
Roman Elizarovfa7723e2017-02-06 11:17:51 +03007<!--- TOC -->
8
Roman Elizarov1293ccd2017-02-01 18:49:54 +03009* [Coroutine basics](#coroutine-basics)
10 * [Your first coroutine](#your-first-coroutine)
11 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
12 * [Waiting for a job](#waiting-for-a-job)
13 * [Extract function refactoring](#extract-function-refactoring)
14 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
15 * [Coroutines are like daemon threads](#coroutines-are-like-daemon-threads)
16* [Cancellation and timeouts](#cancellation-and-timeouts)
17 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
18 * [Cancellation is cooperative](#cancellation-is-cooperative)
19 * [Making computation code cancellable](#making-computation-code-cancellable)
20 * [Closing resources with finally](#closing-resources-with-finally)
21 * [Run non-cancellable block](#run-non-cancellable-block)
22 * [Timeout](#timeout)
23* [Composing suspending functions](#composing-suspending-functions)
24 * [Sequential by default](#sequential-by-default)
25 * [Concurrent using deferred value](#concurrent-using-deferred-value)
26 * [Lazily deferred value](#lazily-deferred-value)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030027* [Coroutine context and dispatchers](#coroutine-context-and-dispatchers)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030028 * [Dispatchers and threads](#dispatchers-and-threads)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +030029 * [Unconfined vs confined dispatcher](#unconfined-vs-confined-dispatcher)
30 * [Debugging coroutines and threads](#debugging-coroutines-and-threads)
31 * [Jumping between threads](#jumping-between-threads)
32 * [Job in the context](#job-in-the-context)
33 * [Children of a coroutine](#children-of-a-coroutine)
34 * [Combining contexts](#combining-contexts)
35 * [Naming coroutines for debugging](#naming-coroutines-for-debugging)
Roman Elizarovb7721cf2017-02-03 19:23:08 +030036* [Channels](#channels)
37 * [Channel basics](#channel-basics)
38 * [Closing and iteration over channels](#closing-and-iteration-over-channels)
39 * [Building channel producers](#building-channel-producers)
40 * [Pipelines](#pipelines)
41 * [Prime numbers with pipeline](#prime-numbers-with-pipeline)
42 * [Fan-out](#fan-out)
43 * [Fan-in](#fan-in)
44 * [Buffered channels](#buffered-channels)
Roman Elizarovfa7723e2017-02-06 11:17:51 +030045
Roman Elizarovb3d55a52017-02-03 12:47:21 +030046<!--- KNIT kotlinx-coroutines-core/src/test/kotlin/guide/.*\.kt -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +030047
Roman Elizarovfa7723e2017-02-06 11:17:51 +030048<!--- INCLUDE .*/example-([a-z]+)-([0-9]+)\.kt
Roman Elizarovb3d55a52017-02-03 12:47:21 +030049// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
Roman Elizarovfa7723e2017-02-06 11:17:51 +030050package guide.$$1.example$$2
Roman Elizarovb3d55a52017-02-03 12:47:21 +030051
52import kotlinx.coroutines.experimental.*
53-->
54
Roman Elizarov1293ccd2017-02-01 18:49:54 +030055## Coroutine basics
56
57This section covers basic coroutine concepts.
58
59### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +030060
61Run the following code:
62
63```kotlin
64fun main(args: Array<String>) {
65 launch(CommonPool) { // create new coroutine in common thread pool
66 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
67 println("World!") // print after delay
68 }
69 println("Hello,") // main function continues while coroutine is delayed
70 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
71}
72```
73
Roman Elizarovfa7723e2017-02-06 11:17:51 +030074> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +030075
76Run this code:
77
78```
79Hello,
80World!
81```
82
83Essentially, coroutines are light-weight threads. You can achieve the same result replacing
84`launch(CommonPool) { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
85
86If you start by replacing `launch(CommonPool)` by `thread`, the compiler produces the following error:
87
88```
89Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
90```
91
92That is because `delay` is a special _suspending function_ that does not block a thread, but _suspends_
93coroutine and it can be only used from a coroutine.
94
Roman Elizarov1293ccd2017-02-01 18:49:54 +030095### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +030096
97The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same
98code of `main` function. It is easy to get lost. Let's cleanly separate blocking and non-blocking
99worlds by using `runBlocking { ... }`:
100
101```kotlin
102fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
103 launch(CommonPool) { // create new coroutine in common thread pool
104 delay(1000L)
105 println("World!")
106 }
107 println("Hello,") // main coroutine continues while child is delayed
108 delay(2000L) // non-blocking delay for 2 seconds to keep JVM alive
109}
110```
111
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300112> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300113
114The result is the same, but this code uses only non-blocking `delay`.
115
116`runBlocking { ... }` works as an adaptor that is used here to start the top-level main coroutine.
117The regular code outside of `runBlocking` _blocks_, until the coroutine inside `runBlocking` is active.
118
119This is also a way to write unit-tests for suspending functions:
120
121```kotlin
122class MyTest {
123 @Test
124 fun testMySuspendingFunction() = runBlocking<Unit> {
125 // here we can use suspending functions using any assertion style that we like
126 }
127}
128```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300129
130<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300131
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300132### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300133
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300134Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
135wait (in a non-blocking way) until the background job coroutine that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300136
137```kotlin
138fun main(args: Array<String>) = runBlocking<Unit> {
139 val job = launch(CommonPool) { // create new coroutine and keep a reference to its Job
140 delay(1000L)
141 println("World!")
142 }
143 println("Hello,")
144 job.join() // wait until child coroutine completes
145}
146```
147
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300148> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300149
150Now the result is still the same, but the code of the main coroutine is not tied to the duration of
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300151the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300152
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300153### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300154
155Let's extract the block of code inside `launch(CommonPool} { ... }` into a separate function. When you
156perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
157That is your first _suspending function_. Suspending functions can be used inside coroutines
158just like regular functions, but their additional feature is that they can, in turn,
159use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
160
161```kotlin
162fun main(args: Array<String>) = runBlocking<Unit> {
163 val job = launch(CommonPool) { doWorld() }
164 println("Hello,")
165 job.join()
166}
167
168// this is your first suspending function
169suspend fun doWorld() {
170 delay(1000L)
171 println("World!")
172}
173```
174
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300175> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-04.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300176
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300177### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300178
179Run the following code:
180
181```kotlin
182fun main(args: Array<String>) = runBlocking<Unit> {
183 val jobs = List(100_000) { // create a lot of coroutines and list their jobs
184 launch(CommonPool) {
185 delay(1000L)
186 print(".")
187 }
188 }
189 jobs.forEach { it.join() } // wait for all jobs to complete
190}
191```
192
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300193> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-05.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300194
195It starts 100K coroutines and, after a second, each coroutine prints a dot.
196Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
197
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300198### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300199
200The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300201returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300202
203```kotlin
204fun main(args: Array<String>) = runBlocking<Unit> {
205 launch(CommonPool) {
206 repeat(1000) { i ->
207 println("I'm sleeping $i ...")
208 delay(500L)
209 }
210 }
211 delay(1300L) // just quit after delay
212}
213```
214
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300215> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-basic-06.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300216
217You can run and see that it prints three lines and terminates:
218
219```
220I'm sleeping 0 ...
221I'm sleeping 1 ...
222I'm sleeping 2 ...
223```
224
225Active coroutines do not keep the process alive. They are like daemon threads.
226
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300227## Cancellation and timeouts
228
229This section covers coroutine cancellation and timeouts.
230
231### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300232
233In small application the return from "main" method might sound like a good idea to get all coroutines
234implicitly terminated. In a larger, long-running application, you need finer-grained control.
235The `launch` function returns a `Job` that can be used to cancel running coroutine:
236
237```kotlin
238fun main(args: Array<String>) = runBlocking<Unit> {
239 val job = launch(CommonPool) {
240 repeat(1000) { i ->
241 println("I'm sleeping $i ...")
242 delay(500L)
243 }
244 }
245 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300246 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300247 job.cancel() // cancels the job
248 delay(1300L) // delay a bit to ensure it was cancelled indeed
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300249 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300250}
251```
252
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300253> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-01.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300254
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300255It produces the following output:
256
257```
258I'm sleeping 0 ...
259I'm sleeping 1 ...
260I'm sleeping 2 ...
261main: I'm tired of waiting!
262main: Now I can quit.
263```
264
265As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
266
267### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300268
Tair Rzayevaf734622017-02-01 22:30:16 +0200269Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300270All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
271coroutine and throw `CancellationException` when cancelled. However, if a coroutine is working in
272a computation and does not check for cancellation, then it cannot be cancelled, like the following
273example shows:
274
275```kotlin
276fun main(args: Array<String>) = runBlocking<Unit> {
277 val job = launch(CommonPool) {
278 var nextPrintTime = 0L
279 var i = 0
280 while (true) { // computation loop
281 val currentTime = System.currentTimeMillis()
282 if (currentTime >= nextPrintTime) {
283 println("I'm sleeping ${i++} ...")
284 nextPrintTime = currentTime + 500L
285 }
286 }
287 }
288 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300289 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300290 job.cancel() // cancels the job
291 delay(1300L) // delay a bit to see if it was cancelled....
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300292 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300293}
294```
295
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300296> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-02.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300297
298Run it to see that it continues to print "I'm sleeping" even after cancellation.
299
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300300### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300301
302There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300303invoke a suspending function. There is a `yield` function that is a good choice for that purpose.
304The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300305
306Replace `while (true)` in the previous example with `while (isActive)` and rerun it.
307
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300308```kotlin
309fun main(args: Array<String>) = runBlocking<Unit> {
310 val job = launch(CommonPool) {
311 var nextPrintTime = 0L
312 var i = 0
313 while (isActive) { // cancellable computation loop
314 val currentTime = System.currentTimeMillis()
315 if (currentTime >= nextPrintTime) {
316 println("I'm sleeping ${i++} ...")
317 nextPrintTime = currentTime + 500L
318 }
319 }
320 }
321 delay(1300L) // delay a bit
322 println("main: I'm tired of waiting!")
323 job.cancel() // cancels the job
324 delay(1300L) // delay a bit to see if it was cancelled....
325 println("main: Now I can quit.")
326}
327```
328
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300329> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-03.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300330
331As you can see, now this loop can be cancelled. `isActive` is a property that is available inside
332the code of coroutines via `CoroutineScope` object.
333
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300334### Closing resources with finally
335
336Cancellable suspending functions throw `CancellationException` on cancellation which can be handled in
337all the usual way. For example, the `try {...} finally {...}` and Kotlin `use` function execute their
338finalization actions normally when coroutine is cancelled:
339
340```kotlin
341fun main(args: Array<String>) = runBlocking<Unit> {
342 val job = launch(CommonPool) {
343 try {
344 repeat(1000) { i ->
345 println("I'm sleeping $i ...")
346 delay(500L)
347 }
348 } finally {
349 println("I'm running finally")
350 }
351 }
352 delay(1300L) // delay a bit
353 println("main: I'm tired of waiting!")
354 job.cancel() // cancels the job
355 delay(1300L) // delay a bit to ensure it was cancelled indeed
356 println("main: Now I can quit.")
357}
358```
359
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300360> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-04.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300361
362The example above produces the following output:
363
364```
365I'm sleeping 0 ...
366I'm sleeping 1 ...
367I'm sleeping 2 ...
368main: I'm tired of waiting!
369I'm running finally
370main: Now I can quit.
371```
372
373### Run non-cancellable block
374
375Any attempt to use a suspending function in the `finally` block of the previous example will cause
376`CancellationException`, because the coroutine running this code is cancelled. Usually, this is not a
377problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
378communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
379rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
380`run(NonCancellable) {...}` as the following example shows:
381
382```kotlin
383fun main(args: Array<String>) = runBlocking<Unit> {
384 val job = launch(CommonPool) {
385 try {
386 repeat(1000) { i ->
387 println("I'm sleeping $i ...")
388 delay(500L)
389 }
390 } finally {
391 run(NonCancellable) {
392 println("I'm running finally")
393 delay(1000L)
394 println("And I've just delayed for 1 sec because I'm non-cancellable")
395 }
396 }
397 }
398 delay(1300L) // delay a bit
399 println("main: I'm tired of waiting!")
400 job.cancel() // cancels the job
401 delay(1300L) // delay a bit to ensure it was cancelled indeed
402 println("main: Now I can quit.")
403}
404```
405
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300406> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-05.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300407
408### Timeout
409
410The most obvious reason to cancel coroutine execution in practice,
411is because its execution time has exceeded some timeout.
412While you can manually track the reference to the corresponding `job` and launch a separate coroutine to cancel
413the tracked one after delay, there is a ready to use `withTimeout(...) {...}` function that does it.
414Look at the following example:
415
416```kotlin
417fun main(args: Array<String>) = runBlocking<Unit> {
418 withTimeout(1300L) {
419 repeat(1000) { i ->
420 println("I'm sleeping $i ...")
421 delay(500L)
422 }
423 }
424}
425```
426
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300427> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-cancel-06.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300428
429It produces the following output:
430
431```
432I'm sleeping 0 ...
433I'm sleeping 1 ...
434I'm sleeping 2 ...
435Exception in thread "main" java.util.concurrent.CancellationException: Timed out waiting for 1300 MILLISECONDS
436```
437
438We have not seen the `CancellationException` stack trace printed on the console before. That is because
439inside a cancelled coroutine `CancellationException` is a considered a normal reason for coroutine completion.
440However, in this example we have used `withTimeout` right inside the `main` function.
441
442Because cancellation is just an exception, all the resources will be closed in a usual way.
443You can wrap the code with timeout in `try {...} catch (e: CancellationException) {...}` block if
444you need to do some additional action specifically on timeout.
445
446## Composing suspending functions
447
448This section covers various approaches to composition of suspending functions.
449
450### Sequential by default
451
452Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300453remote service call or computation. We just pretend they are useful, but actually each one just
454delays for a second for the purpose of this example:
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300455
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300456<!--- INCLUDE .*/example-compose-([0-9]+).kt
457import kotlin.system.measureTimeMillis
458-->
459
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300460```kotlin
461suspend fun doSomethingUsefulOne(): Int {
462 delay(1000L) // pretend we are doing something useful here
463 return 13
464}
465
466suspend fun doSomethingUsefulTwo(): Int {
467 delay(1000L) // pretend we are doing something useful here, too
468 return 29
469}
470```
471
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300472<!--- INCLUDE .*/example-compose-([0-9]+).kt -->
473
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300474What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
475`doSomethingUsefulTwo` and compute the sum of their results?
476In practise we do this if we use the results of the first function to make a decision on whether we need
477to invoke the second one or to decide on how to invoke it.
478
479We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
480code, is _sequential_ by default. The following example demonstrates that by measuring the total
481time it takes to execute both suspending functions:
482
483```kotlin
484fun main(args: Array<String>) = runBlocking<Unit> {
485 val time = measureTimeMillis {
486 val one = doSomethingUsefulOne()
487 val two = doSomethingUsefulTwo()
488 println("The answer is ${one + two}")
489 }
490 println("Completed in $time ms")
491}
492```
493
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300494> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-01.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300495
496It produces something like this:
497
498```
499The answer is 42
500Completed in 2017 ms
501```
502
503### Concurrent using deferred value
504
505What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
506we want to get the answer faster, by doing both _concurrently_? This is where `defer` comes to helps.
507
508Conceptually, `defer` is just like `launch`. It starts a separate coroutine which is a light-weight thread
509that works concurrently with all the other coroutines. The difference is that `launch` returns a `Job` and
510does not carry any resulting value, while `defer` returns a `Deferred` -- a kind of light-weight non-blocking future
511that represent a promise to provide result later. You can use `.await()` on a deferred value to get its eventual result,
512but `Deferred` is also a `Job`, so you can cancel it if needed.
513
514```kotlin
515fun main(args: Array<String>) = runBlocking<Unit> {
516 val time = measureTimeMillis {
517 val one = defer(CommonPool) { doSomethingUsefulOne() }
518 val two = defer(CommonPool) { doSomethingUsefulTwo() }
519 println("The answer is ${one.await() + two.await()}")
520 }
521 println("Completed in $time ms")
522}
523```
524
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300525> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-02.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300526
527It produces something like this:
528
529```
530The answer is 42
531Completed in 1017 ms
532```
533
534This is twice as fast, because we have concurrent execution of two coroutines.
535Note, that concurrency with coroutines is always explicit.
536
537### Lazily deferred value
538
539There is a lazy alternative to `defer` that is called `lazyDefer`. It is just like `defer`, but it
540starts coroutine only when its result is needed by some `await` or if a special `start` function
541is invoked. Run the following example:
542
543```kotlin
544fun main(args: Array<String>) = runBlocking<Unit> {
545 val time = measureTimeMillis {
546 val one = lazyDefer(CommonPool) { doSomethingUsefulOne() }
547 val two = lazyDefer(CommonPool) { doSomethingUsefulTwo() }
548 println("The answer is ${one.await() + two.await()}")
549 }
550 println("Completed in $time ms")
551}
552```
553
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300554> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-03.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300555
556It produces something like this:
557
558```
559The answer is 42
560Completed in 2017 ms
561```
562
563So, we are back to two sequential execution, because we _first_ await for the `one` deferred, _and then_ await
564for the second one. It is not the intended use-case for `lazyDefer`. It is designed as a replacement for
565the standard `lazy` function in cases when computation of the value involve suspending functions.
566
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300567## Coroutine context and dispatchers
568
569We've already seen `launch(CommonPool) {...}`, `defer(CommonPool) {...}`, `run(NonCancellable) {...}`, etc.
570In these code snippets `CommonPool` and `NonCancellable` are _coroutine contexts_.
571This section covers other available choices.
572
573### Dispatchers and threads
574
575Coroutine context includes a _coroutine dispatcher_ which determines what thread or threads
576the corresponding coroutine uses for its execution. Coroutine dispatcher can confine coroutine execution
577to a specific thread, dispatch it to a thread pool, or let it run unconfined. Try the following example:
578
579```kotlin
580fun main(args: Array<String>) = runBlocking<Unit> {
581 val jobs = arrayListOf<Job>()
582 jobs += launch(Unconfined) { // not confined -- will work with main thread
583 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
584 }
585 jobs += launch(context) { // context of the parent, runBlocking coroutine
586 println(" 'context': I'm working in thread ${Thread.currentThread().name}")
587 }
588 jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
589 println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
590 }
591 jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
592 println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
593 }
594 jobs.forEach { it.join() }
595}
596```
597
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300598> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-01.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300599
600It produces the following output (maybe in different order):
601
602```
603 'Unconfined': I'm working in thread main
604 'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1
605 'newSTC': I'm working in thread MyOwnThread
606 'context': I'm working in thread main
607```
608
609The difference between parent `context` and `Unconfied` context will be shown later.
610
611### Unconfined vs confined dispatcher
612
613The `Unconfined` coroutine dispatcher starts coroutine in the caller thread, but only until the
614first suspension point. After suspension it resumes in the thread that is fully determined by the
615suspending function that was invoked. Unconfined dispatcher is appropriate when coroutine does not
616consume CPU time nor updates any shared data (like UI) that is confined to a specific thread.
617
618On the other side, `context` property that is available inside the block of any coroutine
619via `CoroutineScope` interface, is a reference to a context of this particular coroutine.
620This way, a parent context can be inherited. The default context of `runBlocking`, in particular,
621is confined to be invoker thread, so inheriting it has the effect of confining execution to
622this thread with a predictable FIFO scheduling.
623
624```kotlin
625fun main(args: Array<String>) = runBlocking<Unit> {
626 val jobs = arrayListOf<Job>()
627 jobs += launch(Unconfined) { // not confined -- will work with main thread
628 println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
629 delay(1000)
630 println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
631 }
632 jobs += launch(context) { // context of the parent, runBlocking coroutine
633 println(" 'context': I'm working in thread ${Thread.currentThread().name}")
634 delay(1000)
635 println(" 'context': After delay in thread ${Thread.currentThread().name}")
636 }
637 jobs.forEach { it.join() }
638}
639```
640
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300641> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-contest-02.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300642
643Produces the output:
644
645```
646 'Unconfined': I'm working in thread main
647 'context': I'm working in thread main
648 'Unconfined': After delay in thread kotlinx.coroutines.ScheduledExecutor
649 'context': After delay in thread main
650```
651
652So, the coroutine the had inherited `context` of `runBlocking {...}` continues to execute in the `main` thread,
653while the unconfined one had resumed in the scheduler thread that `delay` function is using.
654
655### Debugging coroutines and threads
656
657Coroutines can suspend on one thread and resume on another thread with `Unconfined` dispatcher or
658with a multi-threaded dispatcher like `CommonPool`. Even with a single-threaded dispatcher it might be hard to
659figure out what coroutine was doing what, where, and when. The common approach to debugging applications with
660threads is to print the thread name in the log file on each log statement. This feature is universally supported
661by logging frameworks. When using coroutines, the thread name alone does not give much of a context, so
662`kotlinx.coroutines` includes debugging facilities to make it easier.
663
664Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
665
666```kotlin
667fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
668
669fun main(args: Array<String>) = runBlocking<Unit> {
670 val a = defer(context) {
671 log("I'm computing a piece of the answer")
672 6
673 }
674 val b = defer(context) {
675 log("I'm computing another piece of the answer")
676 7
677 }
678 log("The answer is ${a.await() * b.await()}")
679}
680```
681
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300682> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-03.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300683
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300684There are three coroutines. The main coroutine (#1) -- `runBlocking` one,
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300685and two coroutines computing deferred values `a` (#2) and `b` (#3).
686They are all executing in the context of `runBlocking` and are confined to the main thread.
687The output of this code is:
688
689```
690[main @coroutine#2] I'm computing a piece of the answer
691[main @coroutine#3] I'm computing another piece of the answer
692[main @coroutine#1] The answer is 42
693```
694
695The `log` function prints the name of the thread in square brackets and you can see, that it is the `main`
696thread, but the identifier of the currently executing coroutine is appended to it. This identifier
697is consecutively assigned to all created coroutines when debugging mode is turned on.
698
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300699You can read more about debugging facilities in the documentation for `newCoroutineContext` function.
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300700
701### Jumping between threads
702
703Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
704
705```kotlin
706fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
707
708fun main(args: Array<String>) {
709 val ctx1 = newSingleThreadContext("Ctx1")
710 val ctx2 = newSingleThreadContext("Ctx2")
711 runBlocking(ctx1) {
712 log("Started in ctx1")
713 run(ctx2) {
714 log("Working in ctx2")
715 }
716 log("Back to ctx1")
717 }
718}
719```
720
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300721> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-04.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300722
723It demonstrates two new techniques. One is using `runBlocking` with an explicitly specified context, and
724the second one is using `run(context) {...}` to change a context of a coroutine while still staying in the
725same coroutine as you can see in the output below:
726
727```
728[Ctx1 @coroutine#1] Started in ctx1
729[Ctx2 @coroutine#1] Working in ctx2
730[Ctx1 @coroutine#1] Back to ctx1
731```
732
733### Job in the context
734
735The coroutine `Job` is part of its context. The coroutine can retrieve it from its own context
736using `context[Job]` expression:
737
738```kotlin
739fun main(args: Array<String>) = runBlocking<Unit> {
740 println("My job is ${context[Job]}")
741}
742```
743
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300744> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-05.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300745
746It produces
747
748```
749My job is BlockingCoroutine{isActive=true}
750```
751
752So, `isActive` in `CoroutineScope` is just a convenient shortcut for `context[Job]!!.isActive`.
753
754### Children of a coroutine
755
756When `context` of a coroutine is used to launch another coroutine, the `Job` of the new coroutine becomes
757a _child_ of the parent coroutine's job. When the parent coroutine is cancelled, all its children
758are recursively cancelled, too.
759
760```kotlin
761fun main(args: Array<String>) = runBlocking<Unit> {
762 // start a coroutine to process some kind of incoming request
763 val request = launch(CommonPool) {
764 // it spawns two other jobs, one with its separate context
765 val job1 = launch(CommonPool) {
766 println("job1: I have my own context and execute independently!")
767 delay(1000)
768 println("job1: I am not affected by cancellation of the request")
769 }
770 // and the other inherits the parent context
771 val job2 = launch(context) {
772 println("job2: I am a child of the request coroutine")
773 delay(1000)
774 println("job2: I will not execute this line if my parent request is cancelled")
775 }
776 // request completes when both its sub-jobs complete:
777 job1.join()
778 job2.join()
779 }
780 delay(500)
781 request.cancel() // cancel processing of the request
782 delay(1000) // delay a second to see what happens
783 println("main: Who has survived request cancellation?")
784}
785```
786
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300787> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-06.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300788
789The output of this code is:
790
791```
792job1: I have my own context and execute independently!
793job2: I am a child of the request coroutine
794job1: I am not affected by cancellation of the request
795main: Who has survived request cancellation?
796```
797
798### Combining contexts
799
800Coroutine context can be combined using `+` operator. The context on the right-hand side replaces relevant entries
801of the context on the left-hand side. For example, a `Job` of the parent coroutine can be inherited, while
802its dispatcher replaced:
803
804```kotlin
805fun main(args: Array<String>) = runBlocking<Unit> {
806 // start a coroutine to process some kind of incoming request
807 val request = launch(context) { // use the context of `runBlocking`
808 // spawns CPU-intensive child job in CommonPool !!!
809 val job = launch(context + CommonPool) {
810 println("job: I am a child of the request coroutine, but with a different dispatcher")
811 delay(1000)
812 println("job: I will not execute this line if my parent request is cancelled")
813 }
814 job.join() // request completes when its sub-job completes
815 }
816 delay(500)
817 request.cancel() // cancel processing of the request
818 delay(1000) // delay a second to see what happens
819 println("main: Who has survived request cancellation?")
820}
821```
822
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300823> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-07.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300824
825The expected outcome of this code is:
826
827```
828job: I am a child of the request coroutine, but with a different dispatcher
829main: Who has survived request cancellation?
830```
831
832### Naming coroutines for debugging
833
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300834Automatically assigned ids are good when coroutines log often and you just need to correlate log records
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300835coming from the same coroutine. However, when coroutine is tied to the processing of a specific request
836or doing some specific background task, it is better to name it explicitly for debugging purposes.
837Coroutine name serves the same function as a thread name. It'll get displayed in the thread name that
838is executing this coroutine when debugging more is turned on.
839
840The following example demonstrates this concept:
841
842```kotlin
843fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
844
845fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
846 log("Started main coroutine")
847 // run two background value computations
848 val v1 = defer(CommonPool + CoroutineName("v1coroutine")) {
849 log("Computing v1")
850 delay(500)
851 252
852 }
853 val v2 = defer(CommonPool + CoroutineName("v2coroutine")) {
854 log("Computing v2")
855 delay(1000)
856 6
857 }
858 log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
859}
860```
861
Roman Elizarovfa7723e2017-02-06 11:17:51 +0300862> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-context-08.kt)
Roman Elizarov2f6d7c92017-02-03 15:16:07 +0300863
864The output it produces with `-Dkotlinx.coroutines.debug` JVM option is similar to:
865
866```
867[main @main#1] Started main coroutine
868[ForkJoinPool.commonPool-worker-1 @v1coroutine#2] Computing v1
869[ForkJoinPool.commonPool-worker-2 @v2coroutine#3] Computing v2
870[main @main#1] The answer for v1 / v2 = 42
871```
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300872
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300873## Channels
Roman Elizarov7deefb82017-01-31 10:33:17 +0300874
Roman Elizarovb7721cf2017-02-03 19:23:08 +0300875Deferred values provide a convenient way to transfer a single value between coroutines.
876Channels provide a way to transfer a stream of values.
877
878<!--- INCLUDE .*/example-channel-([0-9]+).kt
879import kotlinx.coroutines.experimental.channels.*
880-->
881
882### Channel basics
883
884A `Channel` is conceptually very similar to `BlockingQueue`. One key difference is that
885instead of a blocking `put` operation it has a suspending `send`, and instead of
886a blocking `take` operation it has a suspending `receive`.
887
888```kotlin
889fun main(args: Array<String>) = runBlocking<Unit> {
890 val channel = Channel<Int>()
891 launch(CommonPool) {
892 // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
893 for (x in 1..5) channel.send(x * x)
894 }
895 // here we print five received integers:
896 repeat(5) { println(channel.receive()) }
897 println("Done!")
898}
899```
900
901> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-01.kt)
902
903### Closing and iteration over channels
904
905Unlike a queue, a channel can be closed to indicate that no more elements are coming.
906On the receiver side it is convenient to use a regular `for` loop to receive elements
907from the channel.
908
909Conceptually, a `close` is like sending a special close token to the channel.
910The iteration stops as soon as this close token is received, so there is a guarantee
911that all previously sent elements before the close are received:
912
913```kotlin
914fun main(args: Array<String>) = runBlocking<Unit> {
915 val channel = Channel<Int>()
916 launch(CommonPool) {
917 for (x in 1..5) channel.send(x * x)
918 channel.close() // we're done sending
919 }
920 // here we print received values using `for` loop (until the channel is closed)
921 for (y in channel) println(y)
922 println("Done!")
923}
924```
925
926> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-02.kt)
927
928### Building channel producers
929
930The pattern where a coroutine is producing a sequence of elements into a channel is quite common.
931You could abstract such a producer into a function that takes channel as its parameter, but this goes contrary
932to common sense that results must be returned from functions. Here is a convenience
933coroutine builder named `buildChannel` that makes it easy to do it right:
934
935```kotlin
936fun produceSquares() = buildChannel<Int>(CommonPool) {
937 for (x in 1..5) send(x * x)
938}
939
940fun main(args: Array<String>) = runBlocking<Unit> {
941 val squares = produceSquares()
942 for (y in squares) println(y)
943 println("Done!")
944}
945```
946
947> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-03.kt)
948
949### Pipelines
950
951Pipeline is a pattern where one coroutine is producing, possibly infinite, stream of values:
952
953```kotlin
954fun produceNumbers() = buildChannel<Int>(CommonPool) {
955 var x = 1
956 while (true) send(x++) // infinite stream of integers starting from 1
957}
958```
959
960And another coroutine or coroutines are receiving that stream, doing some processing, and sending the result.
961In the below example the numbers are just squared:
962
963```kotlin
964fun square(numbers: ReceiveChannel<Int>) = buildChannel<Int>(CommonPool) {
965 for (x in numbers) send(x * x)
966}
967```
968
969The main code starts and connects pipeline:
970
971```kotlin
972fun main(args: Array<String>) = runBlocking<Unit> {
973 val numbers = produceNumbers() // produces integers from 1 and on
974 val squares = square(numbers) // squares integers
975 for (i in 1..5) println(squares.receive()) // print first five
976 println("Done!") // we are done
977 squares.cancel() // need to cancel these coroutines in a larger app
978 numbers.cancel()
979}
980```
981
982> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-04.kt)
983
984We don't have to cancel these coroutines in this example app, because
985[coroutines are like daemon threads](#coroutines-are-like-daemon-threads),
986but in a larger app we'll need to stop our pipeline if we don't need it anymore.
987Alternatively, we could have run pipeline coroutines as
988[children of a coroutine](#children-of-a-coroutine).
989
990### Prime numbers with pipeline
991
992Let's take pipelines to the extreme, with an example that generates prime numbers using a pipeline
993of coroutines. We start with an infinite sequence of numbers. This time we introduce an
994explicit context parameter, so that caller can control where our coroutines run:
995
996<!--- INCLUDE kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt
997import kotlin.coroutines.experimental.CoroutineContext
998-->
999
1000```kotlin
1001fun numbersFrom(context: CoroutineContext, start: Int) = buildChannel<Int>(context) {
1002 var x = start
1003 while (true) send(x++) // infinite stream of integers from start
1004}
1005```
1006
1007The following pipeline stage filters an incoming stream of numbers, removing all the numbers
1008that are divisible by the given prime number:
1009
1010```kotlin
1011fun filter(context: CoroutineContext, numbers: ReceiveChannel<Int>, prime: Int) = buildChannel<Int>(context) {
1012 for (x in numbers) if (x % prime != 0) send(x)
1013}
1014```
1015
1016Now we build our pipeline by starting a stream of numbers from 2, taking a prime number from the current channel,
1017and launching new pipeline stage for each prime number found. The following example prints first ten prime numbers,
1018running the whole pipeline in the context of the main thread:
1019
1020```kotlin
1021fun main(args: Array<String>) = runBlocking<Unit> {
1022 var cur = numbersFrom(context, 2)
1023 for (i in 1..10) {
1024 val prime = cur.receive()
1025 println(prime)
1026 cur = filter(context, cur, prime)
1027 }
1028}
1029```
1030
1031> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-05.kt)
1032
1033The output of this code is:
1034
1035```
10362
10373
10385
10397
104011
104113
104217
104319
104423
104529
1046```
1047
1048### Fan-out
1049
1050Multiple coroutines may receive from the same channel, distributing work between themselves.
1051Let us start with a producer coroutine that is periodically producing integers
1052(ten numbers per second):
1053
1054```kotlin
1055fun produceNumbers() = buildChannel<Int>(CommonPool) {
1056 var x = 1 // start from 1
1057 while (true) {
1058 send(x++) // produce next
1059 delay(100) // wait 0.1s
1060 }
1061}
1062```
1063
1064Then we can have several processor coroutines. In this example, they just print their id and
1065received number:
1066
1067```kotlin
1068fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch(CommonPool) {
1069 while (true) {
1070 val x = channel.receive()
1071 println("Processor #$id received $x")
1072 }
1073}
1074```
1075
1076Now let us launch five processors and let them work for a second. See what happens:
1077
1078```kotlin
1079fun main(args: Array<String>) = runBlocking<Unit> {
1080 val producer = produceNumbers()
1081 repeat(5) { launchProcessor(it, producer) }
1082 delay(1000)
1083 producer.cancel() // cancel producer coroutine and thus kill them all
1084}
1085```
1086
1087> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-06.kt)
1088
1089The output will be similar to the the following one, albeit the processor ids that receive
1090each specific integer may be different:
1091
1092```
1093Processor #2 received 1
1094Processor #4 received 2
1095Processor #0 received 3
1096Processor #1 received 4
1097Processor #3 received 5
1098Processor #2 received 6
1099Processor #4 received 7
1100Processor #0 received 8
1101Processor #1 received 9
1102Processor #3 received 10
1103```
1104
1105Note, that cancelling a producer coroutine closes its channel, thus eventually terminating iteration
1106over the channel that processor coroutines are doing.
1107
1108### Fan-in
1109
1110Multiple coroutines may send to the same channel.
1111For example, let us have a channel of strings, and a suspending function that
1112repeatedly sends a specified string to this channel with a specified delay:
1113
1114```kotlin
1115suspend fun sendString(channel: SendChannel<String>, s: String, time: Long) {
1116 while (true) {
1117 delay(time)
1118 channel.send(s)
1119 }
1120}
1121```
1122
1123Now, let us see what happen if we launch a couple of coroutines sending strings
1124(in this example we launch them in the context of the main thread):
1125
1126```kotlin
1127fun main(args: Array<String>) = runBlocking<Unit> {
1128 val channel = Channel<String>()
1129 launch(context) { sendString(channel, "foo", 200L) }
1130 launch(context) { sendString(channel, "BAR!", 500L) }
1131 repeat(6) { // receive first six
1132 println(channel.receive())
1133 }
1134}
1135```
1136
1137> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-07.kt)
1138
1139The output is:
1140
1141```
1142foo
1143foo
1144BAR!
1145foo
1146foo
1147BAR!
1148```
1149
1150### Buffered channels
1151
1152The channels shown so far had no buffer. Unbuffered channels transfer elements when sender and receiver
1153meet each other (aka rendezvous). If send is invoked first, then it is suspended until receive is invoked,
1154if receive is invoked first, it is suspended until send is invoked.
1155
1156Both `Channel()` factory and `buildChanner{}` builder take an optional `capacity` parameter to
1157specify _buffer size_. Buffer allows senders to send multiple elements before suspending,
1158similar to the `BlockingQueue` with a specified capacity, which blocks when buffer is full.
1159
1160Take a look at the behavior of the following code:
1161
1162```kotlin
1163fun main(args: Array<String>) = runBlocking<Unit> {
1164 val channel = Channel<Int>(4) // create buffered channel
1165 launch(context) { // launch sender coroutine
1166 repeat(10) {
1167 println("Sending $it") // print before sending each element
1168 channel.send(it) // will suspend when buffer is full
1169 }
1170 }
1171 // don't receive anything... just wait....
1172 delay(1000)
1173}
1174```
1175
1176> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-channel-08.kt)
1177
1178It prints "sending" _five_ times using a buffered channel with capacity of _four_:
1179
1180```
1181Sending 0
1182Sending 1
1183Sending 2
1184Sending 3
1185Sending 4
1186```
1187
1188The first four elements are added to the buffer and the sender suspends when trying to send the fifth one.