@@ -40,8 +40,9 @@ This is a short guide on core features of `kotlinx.coroutines` with a series of
4040 * [ Timeout] ( #timeout )
4141* [ Composing suspending functions] ( #composing-suspending-functions )
4242 * [ 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 )
4546* [ Coroutine context and dispatchers] ( #coroutine-context-and-dispatchers )
4647 * [ Dispatchers and threads] ( #dispatchers-and-threads )
4748 * [ 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
511512to invoke the second one or to decide on how to invoke it.
512513
513514We 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
515516time it takes to execute both suspending functions:
516517
517518``` kotlin
@@ -534,22 +535,22 @@ The answer is 42
534535Completed in 2017 ms
535536```
536537
537- ### Concurrent using deferred value
538+ ### Concurrent using async
538539
539540What 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 .
541542
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
543544that 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,
546547but ` Deferred ` is also a ` Job ` , so you can cancel it if needed.
547548
548549``` kotlin
549550fun main (args : Array <String >) = runBlocking<Unit > {
550551 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() }
553554 println (" The answer is ${one.await() + two.await()} " )
554555 }
555556 println (" Completed in $time ms" )
@@ -568,17 +569,17 @@ Completed in 1017 ms
568569This is twice as fast, because we have concurrent execution of two coroutines.
569570Note, that concurrency with coroutines is always explicit.
570571
571- ### Lazily deferred value
572+ ### Lazily started async
572573
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 :
576577
577578``` kotlin
578579fun main (args : Array <String >) = runBlocking<Unit > {
579580 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() }
582583 println (" The answer is ${one.await() + two.await()} " )
583584 }
584585 println (" Completed in $time ms" )
@@ -594,13 +595,57 @@ The answer is 42
594595Completed in 2017 ms
595596```
596597
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 )
600645
601646## Coroutine context and dispatchers
602647
603- We've already seen ` launch(CommonPool) {...} ` , ` defer (CommonPool) {...}` , ` run(NonCancellable) {...} ` , etc.
648+ We've already seen ` launch(CommonPool) {...} ` , ` async (CommonPool) {...}` , ` run(NonCancellable) {...} ` , etc.
604649In these code snippets ` CommonPool ` and ` NonCancellable ` are _ coroutine contexts_ .
605650This section covers other available choices.
606651
@@ -701,11 +746,11 @@ Run the following code with `-Dkotlinx.coroutines.debug` JVM option:
701746fun log (msg : String ) = println (" [${Thread .currentThread().name} ] $msg " )
702747
703748fun main (args : Array <String >) = runBlocking<Unit > {
704- val a = defer (context) {
749+ val a = async (context) {
705750 log(" I'm computing a piece of the answer" )
706751 6
707752 }
708- val b = defer (context) {
753+ val b = async (context) {
709754 log(" I'm computing another piece of the answer" )
710755 7
711756 }
@@ -879,12 +924,12 @@ fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
879924fun main (args : Array <String >) = runBlocking(CoroutineName (" main" )) {
880925 log(" Started main coroutine" )
881926 // run two background value computations
882- val v1 = defer (CommonPool + CoroutineName (" v1coroutine" )) {
927+ val v1 = async (CommonPool + CoroutineName (" v1coroutine" )) {
883928 log(" Computing v1" )
884929 delay(500 )
885930 252
886931 }
887- val v2 = defer (CommonPool + CoroutineName (" v2coroutine" )) {
932+ val v2 = async (CommonPool + CoroutineName (" v2coroutine" )) {
888933 log(" Computing v2" )
889934 delay(1000 )
890935 6
0 commit comments