runBlocking in Kotlin Coroutines with Example

Prerequisite:

As it is known that when the user calls the delay() function in any coroutine, it will not block the thread in which it is running, while the delay() function is called one can do some other operations like updating UI and many more things. As the delay function is a suspend function it has to be called from the coroutine or another suspend function.

Definition of runBlocking() function 

According to official documentation, the runBlocking() function may be defined as:

runBlocking is a coroutine function. By not providing any context, it will get run on the main thread.Runs a new coroutine and blocks the current thread interruptible until its completion. This function should not be used from a coroutine. It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in main functions and in tests.

Kotlin



filter_none

edit
close

play_arrow

link
brightness_4
code

// smaple program in android studio to demonstrate coroutines
package com.example.gfgcoroutines
  
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
  
class MainActivity : AppCompatActivity() {
    val TAG:String="Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        GlobalScope.launch(Dispatchers.Main) {
            delay(3000)
            Log.d(TAG,"User is in the Global Scope ")
            Toast.makeText(applicationContext,"User is in the Global Scope ",Toast.LENGTH_SHORT).show()
        }
        Log.d(TAG,"User is not in the Global Scope ")
        Toast.makeText(applicationContext,"User is not in the Global Scope ",Toast.LENGTH_SHORT).show()
    }
}

chevron_right


Log Output:

Log-Output of the above program (Timestamps in seconds is shown by Oval Circle in image)

Log output

As it can be seen in the log-output that the “User is in the Global Scope” gets printed after the Log of “User is not in the Global Scope” which shows that the GlobalScope start a coroutine, which does not block the main thread, and the other operations can be performed while the delay time get’s over. But when someone wants to call only the suspend function and do not need the coroutine behavior, one can call the suspend function from the runBlocking. So when one wants to call any suspend functions such as delay() and do not care about the asynchronous nature, one can use the runBlocking function. The difference between the calling the suspend function from the GlobalScope.launch{ } and calling the suspend function (eg delay()) from runBlocking{ } is that runBlocking will block the main thread or the thread in which it is used and GlobalScope.launch{ } will not block the main thread, in this case, UI operations can be performed while the thread is delayed.

Another use-case of runBlocking is for testing of the JUnit, in which one needs to access the suspend function from within the test function. One case also uses the runBlocking in order to learn the coroutines in-depth in order to figure out how they work behind the scenes. Let’s see from the examples below how runBlocking actually works:

Kotlin

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.gfgcoroutines
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
  
class MainActivity : AppCompatActivity() 
{
    val TAG="Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) 
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
        Log.d(TAG,"Before run-blocking")
            runBlocking 
              {
              Log.d(TAG,"just entered into the runBlocking ")
              delay(5000)
  
              Log.d(TAG,"start of the run-blocking")
              Log.d(TAG,"End of the runBlocking")
            }
        Log.d(TAG,"after the run blocking")
    }
}

chevron_right


Log Output:

Log-Output of the above program  (Timestamps in seconds is shown by Oval Circle in image)



Log output

The Round oval circle in the above log-output shows the timestamps in which the log output is being printed. It can be clearly seen that when the “just entered into the runBlocking” the delay of 5 sec is encountered, so other operations can not be performed and have to wait for 5 seconds. The Log statement “after the run blocking” which is outside of the runBlocking function too, has to wait for the whole runBlocking function to finish its work. Let’s take another example and try to learn how runBlocking works and how different coroutines can be launched within it.

Kotlin

filter_none

edit
close

play_arrow

link
brightness_4
code

package com.example.gfgcoroutines
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
  
class MainActivity : AppCompatActivity() 
{
    val TAG="Main Activity"
    override fun onCreate(savedInstanceState: Bundle?) 
    {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
        Log.d(TAG,"Before run-blocking")
             runBlocking 
               {
              Log.d(TAG,"just entered into the runBlocking ")
              delay(5000)
              launch(Dispatchers.IO)
             {
                delay(3000L)
                Log.d(TAG,"Finished to coroutine 1")
             }
  
             launch(Dispatchers.IO)
             {
                delay(3000L)
                Log.d(TAG,"Finished to coroutine 2")
             }
              Log.d(TAG,"start of the run-blocking")
              Log.d(TAG,"End of the runBlocking")
             }
         Log.d(TAG,"after the run blocking")
         GlobalScope.launch 
         {
            Log.d(TAG,"Logging in the globalScope")
         }
    }
}

chevron_right


Log Output:

Log-Output of the above program  (Timestamps in seconds is shown by Oval Circle in image)

Log output

It can be seen in the above log-output that both GlobalScope and launch will execute after the delay of runBlocking. As both the coroutine which are launched within runBlocking with launch function will be executed within the same thread, it seems like both the coroutine are running in parallel, but it is not possible since both are running in the same thread, but they are running in an asynchronous manner. So it can be said that users should use coroutine runBlocking only when the user wants to do a JUnit test or want to call only the suspend functions.




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :
Practice Tags :


1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.