https://kotlinlang.org logo
#getting-started
Title
# getting-started
h

harry.singh

06/17/2020, 2:16 PM
Hi! I'm learning Coroutines and trying to wrap my head around how coroutines are run on a thread. So if I run large number of work-heavy coroutines on a thread, it will block that thread but if I run handful of them, there's a very small probability that the thread will be blocked. I'm trying to understand, how and why does coroutines block the thread in the former case and not in the latter one?
a

Adam Powell

06/17/2020, 2:27 PM
It's not as magic as it might look. 🙂 When a coroutine suspends, the thread it was running on can handle other tasks. When a coroutine resumes, it monopolizes that thread until it suspends again. If a coroutine never suspends or does a lot of work between suspend points, the thread it runs on will be occupied for that full time.
a

Andrew

06/17/2020, 3:13 PM
How are you verifying the thread is blocked / not blocked when running only a small number? Does this mean you see the thread idle when there is unfinished work that is supposed to run on them?
h

harry.singh

06/17/2020, 3:16 PM
When a coroutine suspends
When a coroutine resumes
@Adam Powell What or who decide to perform these actions and when? Is it possible that our coroutine will not be resumed if the thread(say, the coroutine was launched on main thread) is rather busy?
How are you verifying the thread is blocked / not blocked when running only a small number?
I tried running coroutines before setting UI file on Android and compared with both cases. The UI was not displayed in the former case but was shown comparatively quickly in the latter one
a

Andrew

06/17/2020, 3:30 PM
yea I am not sure what that really proves, if you run a lot of work on a thread its going to be blocked/slower compared running less work. I assume this was a dedicated thread for each test that the UI was just waiting for it to complete, vs running on the UI thread?
a

Adam Powell

06/17/2020, 3:33 PM
When a coroutine suspends is determined by when some suspend function calls some variant of
suspendCoroutine
. That produces a
Continuation
object, which acts like a callback; when something else calls
resume
on it, the
ContinuationInterceptor
from the continuation's
CoroutineContext
is consulted for how to resume the continuation. Usually this is a
CoroutineDispatcher
, which acts like an
Executor
. The dispatcher is responsible for making sure continuations resume in the right thread.
👍 1
For example, on Android,
Dispatchers.Main
refers to a dispatcher that uses a main thread
Handler
to resume continuations. It's just like calling
<http://Handler.post|Handler.post>
.
h

harry.singh

06/17/2020, 4:52 PM
So, conceptually I can run a network call in a coroutine launched on main thread and it will not lead to
NetworkOnMainThreadException
?
a

Andrew

06/17/2020, 5:15 PM
A coroutine is an abstraction of work to be done, like a wrapper for a task. Although its usually used with threads its not required
👍 1
You start a coroutine on the main thread, inside of that you are still on the main thread but able to switch to a different context for something like a network call
👍 1
h

harry.singh

06/17/2020, 5:23 PM
So the network call in a main thread coroutine(on Android) will not lead to an exception then, right?
a

Andrew

06/17/2020, 5:29 PM
as long as you use something like withContext(Dispatchers.IO) or a network library which handles the threading part for you like retrofit
Not sure if this will run without modifying a bit but...
viewModelScope.launch { println("Thread = " + Thread.currentThread().getId()) withContext(Dispatchers.IO) { println("Thread = " + Thread.currentThread().getId()) } }
both println are in a coroutine but only 2nd is non-main thread
h

harry.singh

06/17/2020, 5:38 PM
When a coroutine resumes, it monopolizes that thread until it suspends again. If a coroutine never suspends or does a lot of work between suspend points, the thread it runs on will be occupied for that full time.
If a coroutine does not occupy a thread always, but is rather suspended and resumed, why do we need to switch to a different thread like
<http://Dispatchers.IO|Dispatchers.IO>
? I get that running a network call in a main thread coroutine will occupy the main thread for a long time, but still it can be done, right? What I understand right now is that moving over to the IO thread means that we just want to suspend the call on a IO thread
a

Andrew

06/17/2020, 5:46 PM
Network call cannot be done on the main thread simply because the Android OS doesn't allow it, most all other environments allow it with the side effect of the UI hanging until it finishes
h

harry.singh

06/17/2020, 5:54 PM
Gotcha! What if we are doing some heavy work(not IO) in a main thread coroutine on Android, will that lead to Application Not Responding or UI hanging as described above?
a

Andrew

06/17/2020, 5:57 PM
Yes, the details on that I'm not sure of but its however android measures "heavy work" on the main thread. Network is simply not allowed even if it would have been relatively quick
👍 1
h

harry.singh

06/17/2020, 6:11 PM
Thanks guys! I think I've more clear understanding of coroutines now
2 Views