Structured Concurrency
Learn about structured concurrency in coroutine builders.
We'll cover the following...
If we start a coroutine on GlobalScope
, the program won’t wait for it. As previously mentioned, coroutines do not block any threads, and nothing prevents the program from ending. This is why, in the example below, we need to call an additional delay
at the end of runBlocking
if we want to see “World!” printed.
package kotlinx.coroutines.app import kotlinx.coroutines.* fun main() = runBlocking { GlobalScope.launch { delay(1000L) println("World 1!") } GlobalScope.launch { delay(2000L) println("World 2!") } println("Hello,") delay(3000L) }
Why do we need GlobalScope
in the first place? We need it because launch
and async
are extension functions on the CoroutineScope
. However, if we look at these definitions and runBlocking
, we’ll see that the block
parameter is a function type whose receiver type is also CoroutineScope
.
fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext,block: suspend CoroutineScope.() -> T): Tfun CoroutineScope.launch(context: CoroutineContext = EmptyCoroutineContext,start: CoroutineStart = CoroutineStart.DEFAULT,block: suspend CoroutineScope.() -> Unit): Jobfun <T> CoroutineScope.async(context: CoroutineContext = EmptyCoroutineContext,start: CoroutineStart = CoroutineStart.DEFAULT,block: suspend CoroutineScope.() -> T): Deferred<T>
This means that we can get rid of the GlobalScope
. Instead, launch
can be called on the receiver provided by runBlocking
...