DEV Community

Harsh Lade
Harsh Lade

Posted on

Coroutines in Kotlin: A Beginner-Friendly Guide

Introduction

You might have come across this definition: "Coroutines are lightweight threads that enable writing asynchronous and non-blocking code." But let’s be honest—it doesn’t make much sense if you’re new to programming or Kotlin. Don’t worry. In this tutorial, we'll break down everything from the basics and build up your understanding of coroutines in a beginner-friendly way.

Coroutines and their need.

To understand coroutines, we must understand some basic terms and definitions.

Program: A program is a set of instructions. Basically, it is the code we write in any language.

Process: A process is a program under execution. When we run our program, it becomes a process.

Thread: A thread is the smallest unit of execution. A thread is a lightweight process. A process can be divided into multiple threads to reduce the workload.

Coroutines: Coroutines are lightweight compared to threads, meaning they require far fewer resources. Unlike threads, coroutines are managed by the Kotlin runtime, making them more efficient and easier to work with.

Don't worry if you are still confused, as we will move forward, you will have a better understanding about the Coroutines.


Need for Coroutines

When we run our application, it runs on a main thread (managed by the Operating System). All operations and UI components run on the main thread. It is fine to run our application on the main thread until our application needs to perform a heavy, long-running task like Input Output Operation. If heavy tasks run on the main thread, the UI may freeze, leading to a poor user experience.

So, we come up with a solution to run these long-running tasks on another secondary thread (called a background thread), so that our main thread can perform its task, and our UI will not freeze. But threads are too expensive, and we have a limit on using threads, so we can't run too many threads for our application, but if we have a large number of long-running tasks, then what will we do?

Here coroutine comes into the scene. With coroutines, we no longer need multiple background threads. A single thread can manage multiple coroutines, each handling a different task like file operations, API calls, or database queries—efficiently and without freezing the UI. For example, we can launch a coroutine to perform a file operation, another one for API call, and another one for Database Queries.


Properties of Coroutines

  • Coroutines are lightweight and require fewer system resources than threads.
  • Like threads, coroutines can run in parallel, suspend, resume, and share data.
  • Coroutines are cheap because they are managed by the Kotlin runtime rather than the OS.

Note: Coroutines are not threads. Threads are very expensive and managed by the operating system.


Working with Threads.

In this section we will learn how to work with threads.

fun main(){
    println("Running on thread: ${Thread.currentThread().name}")//runs on the main thread
    thread{
        println("Running on thread: ${Thread.currentThread().name}")//runs on a new thread
    }
    println("Running on thread: ${Thread.currentThread().name}")//runs on the main thread
}
Enter fullscreen mode Exit fullscreen mode

Output:

Image description

The thread {} block starts a new thread, and Thread.currentThread().name helps us identify which thread the code is running on.

Now, we will see how we can use threads for long-running tasks.

fun main(){
    println("Running on thread: ${Thread.currentThread().name}")//runs on the main thread
    fetchData()
    println("Main thread continues during the network call: ${Thread.currentThread().name}")
}
fun fetchData(){
    thread{
        println("Running on thread: ${Thread.currentThread().name}")
        Thread.sleep(3000) //simulating fake network call
    }
}
Enter fullscreen mode Exit fullscreen mode

When you will run the above code you will see this output:
Running on thread: main
Main thread continues during the network call: main
Fetching data: Thread-0

So, we can conclude that the thread runs concurrently/parallelly as the network call was going on a different thread, and our main thread was free to show any UI changes, providing a smooth user experience.
We can perform the same tasks with the help of coroutines, which will be efficient and less costly.


✅ Conclusion

In this article, you learned the difference between threads and coroutines, why coroutines are more efficient, and how to work with threads in Kotlin. In the next part, we'll dive deeper into coroutines—how to launch them, use suspend functions, and structure them properly for real-world applications.

Top comments (0)