A Job is a handle for a coroutine’s lifecycle. Coroutine builders such as launch return one, allowing start-and-forget work to be cancelled even when it does not produce a value. section 14.6.2
Cancelling launched work
fun main() { runBlocking(Dispatchers.Default) { val launchedJob = launch { log("I'm launched!") delay(1000.milliseconds) log("I'm done!") } val asyncDeferred = async { log("I'm async") delay(1000.milliseconds) log("I'm done!") } delay(200.milliseconds) launchedJob.cancel() asyncDeferred.cancel() } } The two builder results are lifecycle handles: Job represents the launched coroutine, while Deferred represents the asynchronous computation. Calling cancel requests cancellation of the respective coroutine. section 15.2.1
A Job participates in coroutine structure in several related ways:
- It is an element of CoroutineContext and is associated with a coroutine’s lifecycle, including exceptional cancellation. section 14.8
- A coroutine scope’s context also contains a Job, so cancelling that Job can cancel the scope and its work. section 15.2.1
- Under regular structured concurrency, a child failure fails the parent and cancels other children whose results are no longer needed. section 18.2
- SupervisorJob changes that failure relationship: a parent supervises children without allowing one child’s failure to fail the parent. section 18.2
fun main() = runBlocking {
log("The first, parent, coroutine starts")
launch {
log("The second coroutine starts and is ready to be suspended")
delay(100.milliseconds)
log("The second coroutine is resumed")
}
launch {
log("The third coroutine can run in the meantime")
}
log("The first coroutine has launched two more coroutines")
}
Trace parent and child coroutines as launch creates Jobs, delay suspends one child, and another continues in the meantime. section 14.6.2
