Concurrency in Kotlin is the capability of a program to run multiple tasks at the same time.
Kotlin offers different methods to achieve concurrency, like threads, coroutines, and specialized classes known as concurrency primitives, like lock, atomic, and concurrent classes.
In this Answer, we will focus on threads and get introduced to coroutines.
Multithreading allows multiple parts of a program to run simultaneously, thus achieving concurrency.
In the single-threaded approach, tasks are processed in a single sequence. This means that a particular task has to wait for its predecessor to be completed before it can be processed. Therefore:
In the multi-threaded approach, tasks are processed concurrently. This means a particular task does not have to wait for its predecessor to be completed before it can be processed. In multithreading, each part of the program is called a thread, and each thread has a unique execution path.
All threads in a process share resources (e.g., memory, data, etc.) Because of this, multithreading can be very economical as our threads share resources instead of accessing these resources in sequential order.
However, multithreading is complicated, and building safe multithreaded apps can be quite challenging.
We create threads and run some parts of our programs in these threads. There are several ways to do this in Kotlin:
Thread
classclass MyThread : Thread() {public override fun run() {//code to be executed in the new threadprintln("Thread is running")}}// ... some more codefun main() {// creating an instance of the classval myThread = MyThread()//start the thread, calling the run methodmyThread.start()// wait for the thread to finishmyThread.join()}
Runnable
interfaceclass MyRunnableClass: Runnable {public override fun run() {// code to be executed in the new threadprintln("Thread is running")}}// ... some more codefun main() {// creating an instance of the classval myRunnable = MyRunnableClass()// creating a new thread and passing the runnable instanceval runnableThread = Thread(myRunnable)//start the thread, calling the run methodrunnableThread.start()// wait for the thread to finishrunnableThread.join()}
fun main() {val lambdaThread = Thread{// code to be executed in the new threadprintln("Thread is running")}// ... some more code// starting the threadlambdaThread.start()// wait for the thread to finishlambdaThread.join()}
Traditional threads are costly to maintain and, as a result, are not as effective as we hope or imagine. However, Kotlin has coroutines that take care of the costs and complications of parallel programming (or concurrency). They are lightweight, efficient threads that are easy to use.
Coroutines now have a stable library, meaning there won't be any code-breaking changes to their API.
Coroutines are lightweight and very efficient.
Coroutines can significantly improve performance.
They also make code cleaner and easier to write/read.