I have tried reading various tutorials and pages on Kotlin coroutines and even though it kind of makes sense to me, I still don't feel it has clicked and I dont feel ready to jump on writing async non-blocking code with coroutines. I think what i am missing is a diagram or picture of what exactly happens and in what order when a piece of coroutine code executes. How does that code run at the thread level?
launch {
delay(1000)
println("World (${currentThread().name})")
}
println("Hello (${currentThread().name})")
sleep(1500)
My understanding is this. I am happy to be corrected or given a different example to further my understanding.
Line0: Code starts on main thread
Line1: Launches a new coroutine on a new thread (from forkjoin pool i suppose)
Line2: Suspending function so the coroutine suspends and returns the thread to the thread pool (hence being non-blocking)
Line5: Prints on the main thread
Line6: Blocks the main thread for 1.5s
Line3: The coroutine resumes execution on (not sure which thread here - same as the thread before suspension or can be a different thread?). The coroutines prints on that thread and finishes, hence returning the thread to the pool again.
Another question i have is how would the low-level execution change if i wrap the whole code around runBlocking { ... }
Coroutines were added to Kotlin in version 1.3 and are based on established concepts from other languages. On Android, coroutines help to manage long-running tasks that might otherwise block the main thread and cause your app to become unresponsive.
Kotlin coroutines provide much more flexibility than plain reactive programming (the code can be written in an easy to understand sequential way whenever reactive programming is not needed, but can still be written in a reactive programming style when needed by making use of the Kotlin operators on collections)
Answer: a. You should not use them for any foreground task.
The reason is coroutines makes it easier to write async code and operators just feels more natural to use. As a bonus, Flow operators are all kotlin Extension Functions, which means either you, or libraries, can easily add operators and they will not feel weird to use (in RxJava observable.
Your code doesn't actually do anything that would reveal the special nature of coroutines. It makes two threads do their thing concurrently, just as they would do it in plain Java.
It only gets interesting when you launch a coroutine on the same thread you're already on (for example, the main thread). This is one of the things you achieve with a runBlocking
block:
runBlocking {
launch {
delay(1000)
println("Hello from the launched coroutine. My thread is "
+ Thread.currentThread().name)
}
println("Hello from the top-level coroutine. My thread is "
+ Thread.currentThread().name)
}
This will print
Hello from the top-level coroutine. My thread is main
Hello from the launched coroutine. My thread is main
runBlocking
runs an event loop on the calling thread and propagates a reference to it to all the coroutines you launch within it. For example, delay(1000)
will post an event to this event loop, with an indicated delay of one second, and then it will suspend the coroutine. This will allow the main thread to run the rest of the code below launch
. When the time elapses, the event loop will run the event handler, which will in turn resume the coroutine.
An even more educational example is launching a coroutine without any Dispatcher
. This removes the illusion of coroutines looking like threads and reveals their true magic: by calling continuation.resume()
you make the current thread jump right into the middle of the suspended coroutine's block of code, and all that happens using plain Java method calls. I suggest studying this answer where this is explained in detail. If you're interested in an even more in-depth explanation of how plain Java methods can do this trick, I suggest you watch Roman Elizarov explaining this on YouTube.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With