This article describes threading in Kotlin and introduces Kotlin coroutines.
The aim of multithreading is to concurrently allow execution of two or more parts of the program.
Single Thread vs. Multiple threads
Single Threads
In a 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. In reality, this actually means that:
- Some processes would block others creating a “not so great” experience for our user (imagine if the UI thread is blocked for a while)
- It takes a longer time for all tasks to be completed
- We aren’t really utilizing our CPU
Multiple Threads
In a multi-threaded approach, tasks are processed concurrently. This means that 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 unique execution paths.
All threads in a process share resources (e.g. memory, data etc.). Just because of this, multithreading can be very economical because 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.
How do we use Threads?
The traditional way is to create threads and run some parts of our programs in these threads. These are some ways to do this in Kotlin.
- Extending the
Thread
class
class MyThread: Thread() { public override fun run() { doSomething() } } ... // some more code // executing val myThread = MyThread() myThread.start()
- Implementing the
Runnable
interface
class MyRunnableClass: Runnable { public override fun run() { doSomething() } } ... // some more code // executing val runnableThread = Thread(MyRunnableClass()) runnableThread.start()
- Using Lambda Expressions
val lambdaThread = Thread{ doSomething() } ... // some more code // executing lambdaThread.start()
However, using traditional Threads are costly to maintain and as a result are not as effective as we would hope or imagine. However, Kotlin has Coroutines and what they do is take care of the costs and complications of parallel programming (or concurrency). They are lightweight efficient threads that are really easy to use.
Coroutines now have a stable library meaning there won’t be any code breaking changes to their API.
Advantages of using Coroutines
- Coroutines are lightweight and very efficient
- Coroutines can significantly improve performance
- They also make code cleaner and easier to write/read.
In one of my next articles, we would explore the coroutines library for Kotlin.