How to Create and Execute Coroutines in Kotlin
- Coroutines in Kotlin
- Create a New Project and Add Dependencies in Kotlin
- Create and Execute Coroutines Sequentially in Kotlin
- Create and Execute Coroutines Concurrently in Kotlin
- 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 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