JP
03/16/2020, 9:37 AMRun the code and check the log; we can see that all the coroutines still run on the main UI thread. We haven’t yet employed multithreading in any way, but already we have the benefits of running coroutines concurrently!
It’s very easy for us to change this code to run “contributors” coroutines on different threads from the common thread pool. Specifyas the context argument for theDispatchers.Default
function:async
async(Dispatchers.Default) { ... }```
I’m sort of confused. If I don’t specify a dispatcher in the argument for
async
function, isn’t the default dispatcher Dispatchers.Default
? Yet, I did see the logs change
from
147 [AWT-EventQueue-0] INFO Contributors - Clearing result
2251 [AWT-EventQueue-0 @coroutine#1] INFO Contributors - kotlin: loaded 54 repos
2678 [AWT-EventQueue-0 @coroutine#7] INFO Contributors - kotlin-benchmarks: loaded 7 contributors
...
to
164 [AWT-EventQueue-0] INFO Contributors - Clearing result
2172 [AWT-EventQueue-0 @coroutine#1] INFO Contributors - kotlin: loaded 54 repos
2527 [DefaultDispatcher-worker-5 @coroutine#10] INFO Contributors - anko-example: loaded 2 contributors
2621 [DefaultDispatcher-worker-5 @coroutine#9] INFO Contributors - kotlinx.html: loaded 15 contributors
...
But when I read the comments in the source code of Builders.common.kt
, it was stated like this:
* Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [context] argument.
* If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used.
* The parent job is inherited from a [CoroutineScope] as well, but it can also be overridden
* with corresponding [context] element.
and in Dispatchers.kt
, it was stated:
/**
* The default [CoroutineDispatcher] that is used by all standard builders like
* [launch][CoroutineScope.launch], [async][CoroutineScope.async], etc
* if no dispatcher nor any other [ContinuationInterceptor] is specified in their context.
*
* It is backed by a shared pool of threads on JVM. By default, the maximal level of parallelism used
* by this dispatcher is equal to the number of CPU cores, but is at least two.
* Level of parallelism X guarantees that no more than X tasks can be executed in this dispatcher in parallel.
*/
@JvmStatic
public actual val Default: CoroutineDispatcher = createDefaultDispatcher()
Could someone explain what I’m missing?Joffrey
03/16/2020, 9:48 AMDico
03/16/2020, 9:51 AMCoroutineScope
?JP
03/16/2020, 10:47 AMCoroutineScope
or within another suspending function.Joffrey
03/16/2020, 10:48 AM"The default dispatcher for the runBlocking coroutine, in particular, is confined to the invoker thread, so inheriting it has the effect of confining execution to this thread with predictable FIFO scheduling."
https://kotlinlang.org/docs/reference/coroutines/coroutine-context-and-dispatchers.html#unconfined-vs-confined-dispatcherrunBlocking
does provide a Dispatcher that is not the Default
, that’s why you have to specify Default
if you want it in child coroutinesJP
03/16/2020, 11:13 AMrunBlocking
the default dispatcher is not the Default
. This I noticed for the first time. I just checked the code once again, and tried to find the parent context. It was not runBlocking
, but:
main.kt
calls ContributorsUI
class instance, which implements Contributors
interface, which again implements CoroutineScope
interface. The Contributors
interface has method loadContributors
which calls the suspending function loadContributorsConcurrent
, in which the async
call happens.
And I found out inside Contributors
interface the code:
val job: Job
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
I guess this code set the parent context’s dispatcher to Dispatchers.Main
, right?
P.S. How should I interpret the expression job + Dispatchers.Main
? Could someone give a link to read about this? I found in Jobs.kt
public operator fun plus(other: Job) = other
but I think I found the wrong code to read about.Joffrey
03/16/2020, 11:14 AMI guess this code set the parent context’s dispatcher toIt sets this context’s dispatcher to, right?Dispatchers.Main
Main
, and therefore any child coroutine will inherit it by default, unless you specify another one.JP
03/16/2020, 11:15 AMJoffrey
03/16/2020, 11:17 AMHow should I interpret the expression? Could someone give a link to read about this?job + Dispatchers.Main
CoroutineContext
is a set of elements and using +
allows to add/combine such elements (like Job
or Dispatcher
or CoroutineName
) to a context. This is explained in the article I linked in my first reply.JP
03/16/2020, 11:18 AMJoffrey
03/16/2020, 11:18 AM+
operator overloading: https://kotlinlang.org/docs/reference/operator-overloading.html#operator-overloadingJP
03/16/2020, 11:23 AMplus
in Jobs.kt
, but I guess it’s the plus
defined in CoroutineContext
which is called.Joffrey
03/16/2020, 11:24 AMCoroutineContext
type, rather than Job
, in order to enable combining other kinds of CoroutineContext
elements