В чем разница между Launch и Async в Couroutin builder?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между launch и async в Coroutine Builder
В Kotlin Coroutines, launch и async — это два основных билдера для запуска корутин, но они служат разным целям и имеют ключевые различия в поведении и возвращаемых значениях.
Основное назначение
launch используется для запуска корутины, которая выполняет задачу "fire-and-forget" (запустил и забыл). Она не возвращает результат напрямую, а возвращает объект Job, через который можно управлять жизненным циклом корутины (отмена, ожидание завершения). Это аналог выполнения работы в фоновом потоке без ожидания результата.
async предназначена для запуска корутины, которая вычисляет некоторый результат. Она возвращает объект Deferred<T> (который является наследником Job), представляющий "обещание" будущего результата. Для получения самого результата необходимо вызвать await() на объекте Deferred. Это аналог Future или Promise в других языках.
Ключевые различия
-
Возвращаемое значение
launch→Jobasync→Deferred<T>
-
Обработка исключений
- Исключения в
launchнемедленно приводят к сбою родительской корутины, если не обработаны внутри или с помощьюCoroutineExceptionHandler. - Исключения в
asyncне выбрасываются сразу, а "оборачиваются" в объектDeferredи выбрасываются только при вызовеawait().
- Исключения в
-
Предназначение
launch— для фоновых задач, где результат не нужен (логирование, обновление UI после вычислений, отправка аналитики).async— для параллельных вычислений с возвратом результата, часто используется для распараллеливания работы.
Примеры использования
launch — фоновое выполнение без результата
scope.launch {
// Фоновая задача, результат не возвращается
delay(1000)
println("Task completed")
}
// Можно управлять через Job: job.cancel(), job.join()
async — параллельные вычисления с результатом
val deferred1 = scope.async { fetchUserData() }
val deferred2 = scope.async { fetchPosts() }
// Параллельное выполнение, затем ожидание обоих результатов
val user = deferred1.await() // Может выбросить исключение из fetchUserData()
val posts = deferred2.await()
Распараллеливание с async
val time = measureTimeMillis {
val result1 = async { computeSomething(1) }
val result2 = async { computeSomething(2) }
val total = result1.await() + result2.await() // Оба вычисления выполнятся параллельно
}
Важные особенности
asyncнемедленно стартует корутину при вызове (как иlaunch), не дожидаясьawait().await()— suspending функция, которая приостанавливает корутину до получения результата, но не блокирует поток.- Для обработки исключений в
asyncиспользуйте try-catch внутри корутины или вокругawait(). launchсJobпозволяет организовывать иерархии отмены через родительские-дочерние корутины.
Когда что использовать
| Критерий | launch | async |
|---|---|---|
| Нужен результат вычислений | Нет | Да |
| Параллельное выполнение | Не напрямую | Основное применение |
| Обработка исключений | Через CoroutineExceptionHandler | Через try-catch при await() |
| Управление жизненным циклом | Да (через Job) | Да (через Deferred<Job>) |
На практике async часто используется внутри корутины, запущенной через launch, для организации параллельных вычислений, результат которых затем используется для обновления UI или дальнейшей обработки.