
1. Overview
In this article, we will learn about the Kotlin coroutines launch.
2. Kotlin Coroutines
A coroutine is a concurrency design pattern you can use to simplify code that executes asynchronously.
It takes a block of code to run, that works concurrently with the rest of the code. However, it is not bound to any thread. It may suspend its execution in one thread and resume in another one.
Kotlin coroutines are extremely inexpensive when compared with threads. Each time when we want to start a new task asynchronously, we can create a new coroutine. To start a new coroutine
, we use one of the main “coroutine builders”: launch
, async
, or runBlocking
.
JetBrains developed the rich kotlinx.coroutines
library as part of version 1.3 for coroutines.
To learn the differences between launch vs async, refer to this article.
3. Kotlin launch coroutines
The launch
coroutine builder launches a new coroutine without blocking the current thread and returns a reference to the coroutine as a Job
.
fun CoroutineScope.launch( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ): Job
Here is an example of the launch
:
fun main() = runBlocking() { println("main() : ${Thread.currentThread().name}") val job: Job = launch { println("Launch : ${Thread.currentThread().name}") println("Launch : ${Thread.currentThread().name}}") } println("main() : ${Thread.currentThread().name} ") }
If you execute the above code, the following logs appear on the console. As you can see, the code inside the launch block executes asynchronously.
main(): main @coroutine#1 main(): main @coroutine#1 Launch: main @coroutine#2 Launch: main @coroutine#2
4.1. Cancel launch coroutine job
You can call cancel
on the resulting job to cancel the coroutine:
fun main() = runBlocking() { println("main(): ${Thread.currentThread().name}") val job: Job = launch { println("Launch: ${Thread.currentThread().name}") println("Launch: ${Thread.currentThread().name}") } job.cancel() println("main(): ${Thread.currentThread().name}") } /* prints main(): main @coroutine#1 main(): main @coroutine#1 */
4.1. Customize Kotlin launch coroutine execution
By default, the coroutine is immediately scheduled for execution.
However, you can customize the start option by using the start
parameter.
For example, the following launch
coroutine builder contains the start
parameter as CoroutineStart.LAZY to start coroutine lazily. Here, the returned coroutine Job
is in the new state initially and later we explicitly started the coroutine by invoking the start
function of the Job
.
fun main() = runBlocking() { println("main(): ${Thread.currentThread().name}") val job: Job = launch(Dispatchers.Default, CoroutineStart.LAZY) { println("Launch: ${Thread.currentThread().name}") println("Launch corotine: ${Thread.currentThread().name}") } println("Delaying launch code execution to start") delay(1000) job.start() println("main(): ${Thread.currentThread().name}") } /* prints main(): main @coroutine#1 Delaying launch code execution to start main(): main @coroutine#1 Launch: DefaultDispatcher-worker-1 @coroutine#2 Launch: DefaultDispatcher-worker-1 @coroutine#2 */
4.3. launch Coroutines exception
Any uncaught exceptions in this coroutine would also cancel the parent job in the context by default. It means when launch
is applied within another coroutine, then any uncaught exception leads to the cancellation of the parent coroutine as well.
For example, the following main
method contains launch
coroutine within another parent launch
coroutine. If the child coroutine throws any uncaught exception, both parent and child coroutine would be canceled.
fun main() { runBlocking { launch { println("parent: ${Thread.currentThread().name}") val job: Job = launch { println("Launch: ${Thread.currentThread().name}") val i = 100/0 // throw exception println("Launch: ${Thread.currentThread().name}") } job.join() println("parent: ${Thread.currentThread().name}") } } }
If you execute the above code, then you can see the following log statements.
parent: main @coroutine#2 Launch: main @coroutine#3 Exception in thread "main" java.lang.ArithmeticException: / by zero at FileKt$main$1$1$job$1.invokeSuspend (File.kt:14) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run (DispatchedTask.kt:106)
However, you can control this behavior by specifying the CoroutineExceptionHandler
.