Create and Execute Coroutines in Kotlin

Create and Execute Coroutines in Kotlin

  1. Coroutines in Kotlin
  2. Create a New Project and Add Dependencies in Kotlin
  3. Create and Execute Coroutines Sequentially in Kotlin
  4. Create and Execute Coroutines Concurrently in Kotlin
  5. Conclusion

This tutorial will introduce coroutines and show how they can be executed sequentially or concurrently using async- await() in Kotlin.

Coroutines in Kotlin

A coroutine can be viewed as a procedure except that it supports asynchronous programming compared to other normal procedures that only support synchronous programming.

Asynchronous programming is a technique whereby we can suspend a task’s execution at a certain point and delegate the execution to another task as the suspended task waits for some background tasks to be executed. These background tasks can include reading a record from a database, downloading the contents of a web page, and processing a user request from an application.

In synchronous programming, the execution of a task is not suspended at any point, and the thread is used exclusively until the execution is complete.

A coroutine represents this instance of a suspended routine. It can also be viewed as a thread, but a coroutine is not dependent on the underlying thread as it can pause and resume execution on different threads.

In this tutorial, we will learn how to create sequential and concurrent coroutines by ensuring the async- await() functions are executed in the correct order.

Create a New Project and Add Dependencies in Kotlin

Go to IntelliJ and select File > New > Project. On the window that opens, enter kotlinCoroutines as the project name, choose Kotlin on the Language section, Gradle on the Build System section, and press the Create button.

To work with coroutines in Kotlin, we must add the coroutine dependencies to our application. Go to the file build.gradle.kts and ensure you have the following dependencies.

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2")
    testImplementation(kotlin("test"))
}

Ensure you have an active internet connection to download the dependencies. Once the dependencies are downloaded, load the Gradle changes and continue with the next steps.

Create and Execute Coroutines Sequentially in Kotlin

Create the package com/coroutine under the kotlin folder, which will be our application’s base package. Create a Main.kt file under the coroutine folder, and copy and paste the following code into the file.

package com.coroutine

import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

suspend fun executeProcedureOne(): Int{
    delay(3000L)
    println("procedure one executed")
    return 50;
}

suspend fun executeProcedureTwo(): Int{
    delay(1000L)
    println("procedure two executed")
    return 30;
}

fun main(): Unit = runBlocking {
    val value = async {
        executeProcedureOne()
    }
    value.await()
    val secondValue = async {
        executeProcedureTwo()
    }
    secondValue.await()
}

In the above code, we have defined two methods, executeProcedureOne() and executeProcedureTwo(), that can be suspended to perform some background tasks. This is realized using the suspend keyword, as shown above.

Note that these two methods can be suspended without blocking the underlying thread.

We have assigned the main function to a function named runBlocking. The runBlocking function is a builder function that creates a coroutine that runs on the main thread and gets blocked until the coroutines inside the function have finished executing.

Inside the runBlocking function, we have created two async functions that call executeProcedureOne() and executeProcedureTwo() methods, respectively.

The async function is a coroutine builder that creates a new coroutine and returns a Deferred. A Deferred is a future that represents a promise to return a value, and we can use await() to retrieve the value.

Note that calling await() immediately after async will cause the coroutine to be suspended since the inner coroutine is being executed and resumes once it finishes.

The above code executes sequentially as the await() methods after every async function force the coroutine to be suspended until it is complete and it can go to the other coroutines.

Run the above code and note that executeProcedureOne() is completed before executeProcedureTwo() even if it delays the longest time. The output is as shown below.

procedure one executed
procedure two executed

Create and Execute Coroutines Concurrently in Kotlin

Comment the previous code, and copy and paste the following code into the Main.kt file just after the comment.

suspend fun executeProcedureOne(): Int{
    delay(3000L)
    println("procedure one executed")
    return 50;
}

suspend fun executeProcedureTwo(): Int{
    delay(1000L)
    println("procedure two executed")
    return 30;
}

suspend fun executeProcedures() = coroutineScope{
    val firstValue = async {
        executeProcedureOne()
    }

    val secondValue = async {
        executeProcedureTwo()
    }

    firstValue.await()
    secondValue.await()
}

fun main(): Unit = runBlocking  {
    executeProcedures()
}

We have modified the previous example to be concurrent by moving the async coroutine builders to another suspendable function having a coroutineScope and await() after the functions are executed to prevent suspending a coroutine.

The difference between coroutineScope and runBlocking is that the coroutineScope gets suspended and releases the underlying thread to continue executing other tasks.

Run the above code and note that the executeProcedureTwo() method is executed first as it has less delay than the executeProcedureOne() method. The output is shown below.

procedure two executed
procedure one executed

Conclusion

In this tutorial, we have learned what coroutines are and how to execute them sequentially or concurrently leveraging async- await() functions. We have also learned several common concepts in the context of coroutines, including asynchronous programming, synchronous programming, the runBlocking{} function, and the coroutineScope{} function.

David Mbochi Njonge avatar David Mbochi Njonge avatar

David is a back end developer with a major in computer science. He loves to solve problems using technology, learning new things, and making new friends. David is currently a technical writer who enjoys making hard concepts easier for other developers to understand and his work has been published on multiple sites.

LinkedIn GitHub

Related Article - Kotlin Coroutine

  • Difference Between CoroutineScope and coroutineScope in Kotlin