@@ -40,8 +40,9 @@ This is a short guide on core features of `kotlinx.coroutines` with a series of
40
40
* [ Timeout] ( #timeout )
41
41
* [ Composing suspending functions] ( #composing-suspending-functions )
42
42
* [ Sequential by default] ( #sequential-by-default )
43
- * [ Concurrent using deferred value] ( #concurrent-using-deferred-value )
44
- * [ Lazily deferred value] ( #lazily-deferred-value )
43
+ * [ Concurrent using async] ( #concurrent-using-async )
44
+ * [ Lazily started async] ( #lazily-started-async )
45
+ * [ Async-style functions] ( #async-style-functions )
45
46
* [ Coroutine context and dispatchers] ( #coroutine-context-and-dispatchers )
46
47
* [ Dispatchers and threads] ( #dispatchers-and-threads )
47
48
* [ Unconfined vs confined dispatcher] ( #unconfined-vs-confined-dispatcher )
@@ -511,7 +512,7 @@ In practise we do this if we use the results of the first function to make a dec
511
512
to invoke the second one or to decide on how to invoke it.
512
513
513
514
We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
514
- code, is _ sequential_ by default. The following example demonstrates that by measuring the total
515
+ code, is _ sequential_ by default. The following example demonstrates it by measuring the total
515
516
time it takes to execute both suspending functions:
516
517
517
518
``` kotlin
@@ -534,22 +535,22 @@ The answer is 42
534
535
Completed in 2017 ms
535
536
```
536
537
537
- ### Concurrent using deferred value
538
+ ### Concurrent using async
538
539
539
540
What if there are no dependencies between invocation of ` doSomethingUsefulOne ` and ` doSomethingUsefulTwo ` and
540
- we want to get the answer faster, by doing both _ concurrently_ ? This is where ` defer ` comes to helps .
541
+ we want to get the answer faster, by doing both _ concurrently_ ? This is where ` async ` comes to help .
541
542
542
- Conceptually, ` defer ` is just like ` launch ` . It starts a separate coroutine which is a light-weight thread
543
+ Conceptually, ` async ` is just like ` launch ` . It starts a separate coroutine which is a light-weight thread
543
544
that works concurrently with all the other coroutines. The difference is that ` launch ` returns a ` Job ` and
544
- does not carry any resulting value, while ` defer ` returns a ` Deferred ` -- a kind of light-weight non-blocking future
545
- that represent a promise to provide result later. You can use ` .await() ` on a deferred value to get its eventual result,
545
+ does not carry any resulting value, while ` async ` returns a ` Deferred ` -- a light-weight non-blocking future
546
+ that represents a promise to provide a result later. You can use ` .await() ` on a deferred value to get its eventual result,
546
547
but ` Deferred ` is also a ` Job ` , so you can cancel it if needed.
547
548
548
549
``` kotlin
549
550
fun main (args : Array <String >) = runBlocking<Unit > {
550
551
val time = measureTimeMillis {
551
- val one = defer (CommonPool ) { doSomethingUsefulOne() }
552
- val two = defer (CommonPool ) { doSomethingUsefulTwo() }
552
+ val one = async (CommonPool ) { doSomethingUsefulOne() }
553
+ val two = async (CommonPool ) { doSomethingUsefulTwo() }
553
554
println (" The answer is ${one.await() + two.await()} " )
554
555
}
555
556
println (" Completed in $time ms" )
@@ -568,17 +569,17 @@ Completed in 1017 ms
568
569
This is twice as fast, because we have concurrent execution of two coroutines.
569
570
Note, that concurrency with coroutines is always explicit.
570
571
571
- ### Lazily deferred value
572
+ ### Lazily started async
572
573
573
- There is a lazy alternative to ` defer ` that is called ` lazyDefer ` . It is just like ` defer ` , but it
574
- starts coroutine only when its result is needed by some ` await ` or if a special ` start ` function
575
- is invoked. Run the following example:
574
+ There is a laziness option to ` async ` with ` start = false ` parameter.
575
+ It starts coroutine only when its result is needed by some ` await ` or if a ` start ` function
576
+ is invoked. Run the following example that differs from the previous one only by this option :
576
577
577
578
``` kotlin
578
579
fun main (args : Array <String >) = runBlocking<Unit > {
579
580
val time = measureTimeMillis {
580
- val one = lazyDefer (CommonPool ) { doSomethingUsefulOne() }
581
- val two = lazyDefer (CommonPool ) { doSomethingUsefulTwo() }
581
+ val one = async (CommonPool , start = false ) { doSomethingUsefulOne() }
582
+ val two = async (CommonPool , start = false ) { doSomethingUsefulTwo() }
582
583
println (" The answer is ${one.await() + two.await()} " )
583
584
}
584
585
println (" Completed in $time ms" )
@@ -594,13 +595,57 @@ The answer is 42
594
595
Completed in 2017 ms
595
596
```
596
597
597
- So, we are back to two sequential execution, because we _ first_ await for the ` one ` deferred, _ and then_ await
598
- for the second one. It is not the intended use-case for ` lazyDefer ` . It is designed as a replacement for
599
- the standard ` lazy ` function in cases when computation of the value involve suspending functions.
598
+ So, we are back to sequential execution, because we _ first_ start and await for ` one ` , _ and then_ start and await
599
+ for ` two ` . It is not the intended use-case for laziness. It is designed as a replacement for
600
+ the standard ` lazy ` function in cases when computation of the value involves suspending functions.
601
+
602
+ ### Async-style functions
603
+
604
+ We can define async-style functions that invoke ` doSomethingUsefulOne ` and ` doSomethingUsefulTwo `
605
+ _ asynchronously_ using ` async ` coroutine builder. It is a good style to name such functions with
606
+ either "async" prefix of "Async" suffix to highlight the fact that they only start asynchronous
607
+ computation and one needs to use the resulting deferred value to get the result.
608
+
609
+ ``` kotlin
610
+ // The result type of asyncSomethingUsefulOne is Deferred<Int>
611
+ fun asyncSomethingUsefulOne () = async(CommonPool ) {
612
+ doSomethingUsefulOne()
613
+ }
614
+
615
+ // The result type of asyncSomethingUsefulTwo is Deferred<Int>
616
+ fun asyncSomethingUsefulTwo () = async(CommonPool ) {
617
+ doSomethingUsefulTwo()
618
+ }
619
+ ```
620
+
621
+ Note, that these ` asyncXXX ` function are ** not** _ suspending_ functions. They can be used from anywhere.
622
+ However, their use always implies asynchronous (here meaning _ concurrent_ ) execution of their action
623
+ with the invoking code.
624
+
625
+ The following example shows their use outside of coroutine:
626
+
627
+ ``` kotlin
628
+ // note, that we don't have `runBlocking` to the right of `main` in this example
629
+ fun main (args : Array <String >) {
630
+ val time = measureTimeMillis {
631
+ // we can initiate async actions outside of a coroutine
632
+ val one = asyncSomethingUsefulOne()
633
+ val two = asyncSomethingUsefulTwo()
634
+ // but waiting for a result must involve either suspending or blocking.
635
+ // here we use `runBlocking { ... }` to block the main thread while waiting for the result
636
+ runBlocking {
637
+ println (" The answer is ${one.await() + two.await()} " )
638
+ }
639
+ }
640
+ println (" Completed in $time ms" )
641
+ }
642
+ ```
643
+
644
+ > You can get full code [ here] ( kotlinx-coroutines-core/src/test/kotlin/guide/example-compose-04.kt )
600
645
601
646
## Coroutine context and dispatchers
602
647
603
- We've already seen ` launch(CommonPool) {...} ` , ` defer (CommonPool) {...}` , ` run(NonCancellable) {...} ` , etc.
648
+ We've already seen ` launch(CommonPool) {...} ` , ` async (CommonPool) {...}` , ` run(NonCancellable) {...} ` , etc.
604
649
In these code snippets ` CommonPool ` and ` NonCancellable ` are _ coroutine contexts_ .
605
650
This section covers other available choices.
606
651
@@ -701,11 +746,11 @@ Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
701
746
fun log (msg : String ) = println (" [${Thread .currentThread().name} ] $msg " )
702
747
703
748
fun main (args : Array <String >) = runBlocking<Unit > {
704
- val a = defer (context) {
749
+ val a = async (context) {
705
750
log(" I'm computing a piece of the answer" )
706
751
6
707
752
}
708
- val b = defer (context) {
753
+ val b = async (context) {
709
754
log(" I'm computing another piece of the answer" )
710
755
7
711
756
}
@@ -879,12 +924,12 @@ fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
879
924
fun main (args : Array <String >) = runBlocking(CoroutineName (" main" )) {
880
925
log(" Started main coroutine" )
881
926
// run two background value computations
882
- val v1 = defer (CommonPool + CoroutineName (" v1coroutine" )) {
927
+ val v1 = async (CommonPool + CoroutineName (" v1coroutine" )) {
883
928
log(" Computing v1" )
884
929
delay(500 )
885
930
252
886
931
}
887
- val v2 = defer (CommonPool + CoroutineName (" v2coroutine" )) {
932
+ val v2 = async (CommonPool + CoroutineName (" v2coroutine" )) {
888
933
log(" Computing v2" )
889
934
delay(1000 )
890
935
6
0 commit comments