Поведение runBlocking при работе с async‑корутинами

Сначала обычно появятся 1 и 2 в неопределённом порядке, затем 3 и строка First Async Second Async. Гарантирован порядок await в итоговой строке, но не планирование Default-потоков.

Короткий ответ

Что ответить на собеседовании

Сначала обычно появятся 1 и 2 в неопределённом порядке, затем 3 и строка First Async Second Async. Гарантирован порядок await в итоговой строке, но не планирование Default-потоков.

Подробный разбор

Ответ с пояснениями

Условие

Определите, какой вывод появится в консоли после выполнения следующей программы:

val coroutineContext = Job() + Dispatchers.Default
val mainScope = CoroutineScope(coroutineContext)

val first = mainScope.async {
    println(1)
    delay(400)
    "First Async"
}

val second = mainScope.async {
    println(2)
    delay(100)
    "Second Async"
}

runBlocking {
    delay(300)
    println(3)
    println("${first.await()} ${second.await()}")
}

Ответ

Сначала обычно появятся 1 и 2 в неопределённом порядке, затем 3 и строка First Async Second Async. Гарантирован порядок await в итоговой строке, но не планирование Default-потоков.

Обе async запускаются до runBlocking и выполняются независимо в mainScope. second имеет меньшую задержку, но результат выводится после ожидания first, потому что выражение строки вычисляется слева направо. Число 3 печатается перед итоговой строкой. Миллисекундные задержки не гарантируют точное время запуска: при задержке планировщика даже относительное положение 3 и первых println нельзя считать строгим контрактом.

Источник: kotlinlang.org.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее