Kotlin Coroutines Async Await Sequence

toffor picture toffor · Sep 17, 2018 · Viewed 14.5k times · Source

Can you please explain me what is the difference between these two blocks of code. First time prints 421, but second prints 606. Why first one is parallel and second one is sequential?

fun main(args: Array<String>) = runBlocking {

    var time = measureTimeMillis {
        val one = async { one() }
        val two = async { two() }
        val int1 = one.await()
        val int2 = two.await()
        println(int1 + int2)

    }

    println(time)


    time = measureTimeMillis {
        val one = async { one() }.await()
        val two = async { two() }.await()
        println(one + two)

    }

    print(time)
}

suspend fun one(): Int {
    delay(200)
    return 12
}

suspend fun two(): Int {
    delay(400)
    return 23
}

Answer

Marko Topolnik picture Marko Topolnik · Sep 17, 2018
val one = async { one() }
val two = async { two() }
val int1 = one.await()
val int2 = two.await()

What this does:

  1. spawn task one
  2. spawn task two
  3. await on task one
  4. await on task two

val one = async { one() }.await()
val two = async { two() }.await()

What this does:

  1. spawn task one
  2. await on task one
  3. spawn task two
  4. await on task two

There's no concurrency here, it's purely sequential code. In fact, for sequential execution you shouldn't even use async. The proper idiom is

val one = withContext(Dispatchers.Default) { one() }
val two = withContext(Dispatchers.Default) { two() }