← Back to Kotlin Course | Chapter 12: Coroutines | Lesson 2 of 7

launch and async

launch starts a background task you don't need an answer back from, while async starts one where you'll come back later to collect its result.

Using launch for Fire-and-Forget Work

launch { } starts a new coroutine intended for side effects, like printing or updating state, and returns a Job that represents that running task, but no computed value.

Warning: This example uses kotlinx.coroutines, which is not part of the plain Kotlin standard library. It requires the kotlinx-coroutines-core dependency (added via Gradle/Maven) to compile and run.

Example: Using launch for Fire-and-Forget Work

markup
import kotlinx.coroutines.*

fun main() = runBlocking {
    val job = launch {
        println("Doing background work")
    }
    job.join()
    println("Background work complete")
}

Using async for a Result

async { } starts a coroutine that computes and returns a value, wrapped in a Deferred<T>; calling .await() on it suspends until the result is ready and then returns it.

Warning: This example uses kotlinx.coroutines, which is not part of the plain Kotlin standard library. It requires the kotlinx-coroutines-core dependency (added via Gradle/Maven) to compile and run.

Example: Using async for a Result

markup
import kotlinx.coroutines.*

fun main() = runBlocking {
    val deferred = async {
        delay(50)
        42
    }
    println("Result: ${deferred.await()}")
}

Running Multiple async Tasks Concurrently

Starting several async calls before awaiting any of them lets all of those coroutines run concurrently, and the total time is closer to the longest single task rather than the sum of all of them.

Warning: This example uses kotlinx.coroutines, which is not part of the plain Kotlin standard library. It requires the kotlinx-coroutines-core dependency (added via Gradle/Maven) to compile and run.

Example: Running Multiple async Tasks Concurrently

markup
import kotlinx.coroutines.*

fun main() = runBlocking {
    val first = async { delay(100); 10 }
    val second = async { delay(100); 20 }
    val total = first.await() + second.await()
    println("Total: $total")
}

Choosing Between launch and async

Use launch when you don't need a result back from the coroutine, and async when you do -- reaching for async and never calling .await() is a common source of wasted concurrency.

Warning: This example uses kotlinx.coroutines, which is not part of the plain Kotlin standard library. It requires the kotlinx-coroutines-core dependency (added via Gradle/Maven) to compile and run.

Example: Choosing Between launch and async

markup
import kotlinx.coroutines.*

fun main() = runBlocking {
    launch { println("Just logging, no result needed") }
    val value = async { 100 }.await()
    println("Computed value: $value")
}
Common Mistakes
  1. Forgetting to call .await() on a Deferred from async, meaning you never actually retrieve its computed result.
  2. Using async when launch would do, adding unnecessary overhead when no return value is actually needed.
  3. Starting several async calls but calling .await() on each immediately instead of after starting all of them, losing the benefit of running them concurrently.
Chapter Summary
  • launch { } starts a coroutine that runs for its side effects and returns a Job, with no result value.
  • async { } starts a coroutine that computes a result, returned as a Deferred<T>, retrieved later with .await().
  • Starting multiple async calls before awaiting any of them lets them run concurrently rather than sequentially.
  • Both launch and async are coroutine builders provided by kotlinx.coroutines.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.