Non-blocking in Kotlin Coroutines

· 2 min read
Non-blocking in Kotlin Coroutines
Kotlin Coroutines Table Content

1, Introduction to Coroutine in Kotlin
2, Non-blocking in Kotlin Coroutines (This article)
3, Start and Suspend a Coroutine in Kotlin (incoming this week)

From the last article, Introduction to Coroutine in Kotlin, it is known that Coroutine in Kotlin provides advantages such as lightweight,  non-blocking and so on. So what is exactly the non-blocking?

From the name itself, "non-blocking" refers to the ability of a coroutine to run asynchronously, without blocking the execution of other parts of the program. When a function or operation is said to be "blocking," it means that it stops or "blocks" the execution of the program until that function or operation has completed. In fact, majority of code what we saw and wrote everyday is "blocking":

val a = 1
val b = 2
print("a+b = ${a+b}")
// output: a+b = 3

See the code above, the code is blocking, but due to it can be run quickly, as a human we can't sense the "delay".

In contrast, a non-blocking function or operation allows the program to continue executing other code while it is still running. Take a look at the example in the last article:

println("thread 1: ${Thread.currentThread().name}")
  val result = GlobalScope.async {
  println("thread 2: ${Thread.currentThread().name}")
  return@async URL("https://catfact.ninja/fact").readText()
}
runBlocking {
  val data = result.await()
  println(data)
}

The async function call is non-blocking, this mean that the program will continue to execute while the network request is being made. The output:

thread 1: main
thread 2: DefaultDispatcher-worker-1
{"fact":"The largest breed of cat is the Ragdoll"}

As we can see the new Coroutine we created is running in a different thread and that is why it is "non-blocking". This is achieved by the underlying mechanism of the coroutines. Coroutines are lightweight threads that do not consume system resources like an actual thread. They are scheduled by a coroutine dispatcher and they can yield control back to the dispatcher after performing some computation, allowing other coroutines to run. This way, non-blocking operation can be achieved, which is the main advantage of using coroutines over traditional blocking operations.