В kotlinx.coroutines
библиотеке вы можете запустить новую сопрограмму, используя launch
(с join
) или async
(с await
). В чем разница между ними?
источник
В kotlinx.coroutines
библиотеке вы можете запустить новую сопрограмму, используя launch
(с join
) или async
(с await
). В чем разница между ними?
launch
используется, чтобы запустить и забыть сопрограмму . Это как начать новую тему. Если код внутри launch
завершается с исключением, то он обрабатывается как неперехваченное исключение в потоке - обычно выводится на stderr в приложениях JVM бэкэнда и приводит к сбою приложений Android. join
используется для ожидания завершения запущенной сопрограммы и не распространяет ее исключение. Однако, аварийный дочерний сопрограмма отменяет своего родителя также с соответствующим исключением.
async
используется для запуска сопрограммы, которая вычисляет некоторый результат . Результат представлен экземпляром, Deferred
и вы должны использовать await
его. Непонятное исключение внутри async
кода хранится в полученном результате Deferred
и не доставляется куда-либо еще, оно будет автоматически отброшено, если не будет обработано. Вы НЕ ДОЛЖНЫ забывать о сопрограмме, которую вы начали с async .
Я считаю это руководство https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md полезным. Я процитирую основные части
🦄 сопрограмма
Таким образом, вы можете думать о сопрограмме как о чем-то, что очень эффективно управляет потоком.
🐤 запуск
Так что
launch
запускает фоновый поток, что-то делает и сразу возвращает токен какJob
. Вы можете вызватьjoin
это,Job
чтобы заблокировать, пока этотlaunch
поток не завершитсяYn асинхронный
Так что
async
запускает фоновый поток, что-то делает и сразу возвращает токен какDeferred
.Так
Deferred
на самом делеJob
. См. Https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.htmlYn асинхронный по умолчанию
источник
launch
иasync
используются для запуска новых сопрограмм. Но они исполняют их по-разному.Я хотел бы показать очень простой пример, который поможет вам понять разницу очень легко
В этом примере мой код загружает 3 данные по нажатию
btnCount
кнопки и показываетpgBar
индикатор выполнения, пока не будет завершена вся загрузка. Есть 3suspend
функцииdownloadTask1()
,downloadTask2()
иdownloadTask3()
которые загружают данные. Чтобы смоделировать это, я использовалdelay()
в этих функциях. Эти функции ждет5 seconds
,8 seconds
и5 seconds
соответственно.Как мы уже использовали
launch
для запуска этих функций приостановки,launch
будем выполнять их последовательно (один за другим) . Это означает,downloadTask2()
что запускается послеdownloadTask1()
завершения иdownloadTask3()
запускается только послеdownloadTask2()
завершения.Как и на выходном скриншоте
Toast
, общее время выполнения для завершения всех 3 загрузок приведет к 5 секундам + 8 секундам + 5 секундам = 18 секундам сlaunch
Как мы видели, это
launch
делает выполнениеsequentially
для всех 3 задач. Время для выполнения всех задач было18 seconds
.Если эти задачи независимы и если они не нуждаются в результате вычисления другой задачи, мы можем заставить их работать
concurrently
. Они запускаются одновременно и работают одновременно в фоновом режиме. Это можно сделать с помощьюasync
.async
возвращает экземплярDeffered<T>
типа, гдеT
тип данных, который возвращает наша функция приостановки. Например,downloadTask1()
вернется, такDeferred<String>
как String является типом возвращаемого значения функцииdownloadTask2()
вернется, такDeferred<Int>
как Int является типом возвращаемого значения функцииdownloadTask3()
вернется, такDeferred<Float>
как Float является возвращаемым типом функцииМы можем использовать возвращаемый объект
async
типа,Deferred<T>
чтобы получить возвращаемое значениеT
типа. Это можно сделать с помощьюawait()
звонка. Проверьте код ниже, напримерТаким образом, мы запустили все 3 задачи одновременно. Таким образом, мое общее время выполнения будет только то,
8 seconds
что является временем,downloadTask2()
поскольку оно является самым большим из всех трех задач. Вы можете увидеть это на следующем скриншоте вToast message
источник
launch
это для последовательных шуток, аasync
для одновременныхlaunch
и другоеasync
запустит новые сопрограммы. Вы сравниваете одну сопрограмму без детей с одной сопрограммой с 3 детьми. Вы можете заменить каждыйasync
вызов на,launch
и абсолютно ничего не изменится в отношении параллелизма.оба компилятора сопрограмм, а именно launch и async, в основном являются лямбдами с приемником типа CoroutineScope, что означает, что их внутренний блок скомпилирован как функция приостановки, следовательно, они оба работают в асинхронном режиме И оба будут выполнять свой блок последовательно.
Разница между запуском и асинхронностью заключается в том, что они предоставляют две разные возможности. Конструктор запуска возвращает задание, однако асинхронная функция возвращает отложенный объект. Вы можете использовать запуск, чтобы выполнить блок, для которого вы не ожидаете никакого возвращаемого значения, т.е. записи в базу данных или сохранения файла или обработки чего-то, что в основном вызывается для побочного эффекта. С другой стороны, async, который возвращает Deferred, как я уже говорил ранее, возвращает полезное значение из выполнения его блока, объекта, который оборачивает ваши данные, так что вы можете использовать его главным образом для результата, но, возможно, и для его побочного эффекта. NB: вы можете удалить отложенное и получить его значение, используя функцию await, которая будет блокировать выполнение ваших операторов до тех пор, пока не будет возвращено значение или не будут сгенерированы исключения!
оба сопрограммных компоновщика (запуск и асинхронность) могут быть отменены.
что-нибудь еще? Да с запуском, если исключение выдается в его блоке, сопрограмма автоматически отменяется, и исключения доставляются. С другой стороны, если это происходит с асинхронным, исключение не распространяется дальше и должно быть перехвачено / обработано в возвращенном Отложенном объекте.
больше о сопрограммах https://kotlinlang.org/docs/tutorials/coroutines/coroutines-basic-jvm.html https://www.codementor.io/blog/kotlin-coroutines-6n53p8cbn1
источник
запуск возвращает работу
async возвращает результат (отложенное задание)
Запуск с объединением используется для ожидания завершения задания. Он просто приостанавливает вызов сопрограммы join (), оставляя текущий поток свободным для выполнения другой работы (например, выполнения другой сопрограммы).
async используется для вычисления некоторых результатов. Он создает сопрограмму и возвращает свой будущий результат в качестве реализации отложенного. Запуск сопрограммы отменяется, когда отменяется результирующая отсрочка.
Рассмотрим асинхронный метод, который возвращает строковое значение. Если асинхронный метод используется без await, он вернет отложенную строку, но если используется await, вы получите строку в результате
Ключевая разница между асинхронностью и запуском. Отложенный возвращает конкретное значение типа T после того, как ваш Coroutine завершит выполнение, а Job - нет.
источник
Async vs Launch Async vs Launch Diff Image
запуск / асинхронный безрезультатно
асинхронный для результата
источник