En la kotlinx.coroutinesbiblioteca, puede comenzar una nueva rutina utilizando launch(con join) o async(con await). ¿Cuál es la diferencia entre ellos?
fuente
En la kotlinx.coroutinesbiblioteca, puede comenzar una nueva rutina utilizando launch(con join) o async(con await). ¿Cuál es la diferencia entre ellos?
launchSe utiliza para disparar y olvidar la corutina . Es como comenzar un nuevo hilo. Si el código dentro del launchtermina con excepción, entonces se trata como una excepción no capturada en un hilo, generalmente impreso en stderr en aplicaciones JVM de back-end y bloquea las aplicaciones de Android. joinse utiliza para esperar la finalización de la rutina lanzada y no propaga su excepción. Sin embargo, una rutina infantil caída también cancela a su padre con la excepción correspondiente.
asyncse usa para iniciar una rutina que calcula algún resultado . El resultado está representado por una instancia de Deferredy debe usarlo await. Una excepción no detectada dentro del asynccódigo se almacena dentro del resultado Deferredy no se entrega en ningún otro lugar, se eliminará silenciosamente a menos que se procese. NO DEBE olvidarse de la rutina que comenzó con async .
Encuentro útil esta guía https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md . Citaré las partes esenciales
🦄 corutina
Por lo tanto, puede pensar en la rutina como algo que gestiona el hilo de una manera muy eficiente.
🐤 lanzamiento
Entonces
launchcomienza un hilo de fondo, hace algo y devuelve un token inmediatamente comoJob. Puede invocarjoinestoJobpara bloquear hasta que estelaunchhilo se complete🦆 asíncrono
Entonces
asynccomienza un hilo de fondo, hace algo y devuelve un token inmediatamente comoDeferred.Entonces
Deferredes en realidad unJob. Ver https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-deferred/index.html🦋 async está ansioso por defecto
fuente
launchyasyncse utilizan para comenzar nuevas corutinas. Pero, los ejecutan de manera diferente.Me gustaría mostrar un ejemplo muy básico que te ayudará a entender la diferencia muy fácilmente.
En este ejemplo, mi código está descargando 3 datos al hacer clic en el
btnCountbotón y mostrandopgBarla barra de progreso hasta que se complete toda la descarga. Hay 3suspendfuncionesdownloadTask1(),downloadTask2()ydownloadTask3()que descarga datos. Para simularlo, lo he usadodelay()en estas funciones. Estas funciones espera a5 seconds,8 secondsy5 secondsrespectivamente.Como hemos usado
launchpara iniciar estas funciones de suspensión, laslaunchejecutaremos secuencialmente (una por una) . Esto significa quedownloadTask2()comenzaría después dedownloadTask1()completarse ydownloadTask3()comenzaría solo después dedownloadTask2()completarse.Como en la captura de pantalla de salida
Toast, el tiempo total de ejecución para completar las 3 descargas llevaría a 5 segundos + 8 segundos + 5 segundos = 18 segundos conlaunchComo vimos, eso
launchhace que la ejecuciónsequentiallyde las 3 tareas. El momento para completar todas las tareas fue18 seconds.Si esas tareas son independientes y no necesitan el resultado de cálculo de otra tarea, podemos hacer que se ejecuten
concurrently. Comenzarían al mismo tiempo y se ejecutarían simultáneamente en segundo plano. Esto se puede hacer conasync.asyncdevuelve una instancia deDeffered<T>tipo, dondeTes el tipo de datos que devuelve nuestra función de suspensión. Por ejemplo,downloadTask1()volveríaDeferred<String>como String es el tipo de función de retornodownloadTask2()volveríaDeferred<Int>como Int es el tipo de función de retornodownloadTask3()regresaríaDeferred<Float>como Float es el tipo de función de retornoPodemos usar el objeto de devolución from
asyncof typeDeferred<T>para obtener el valor devuelto enTtype. Eso se puede hacer conawait()llamada. Verifique el siguiente código, por ejemploDe esta manera, hemos lanzado las 3 tareas al mismo tiempo. Entonces, mi tiempo total de ejecución para completar sería solo
8 secondsel tiempo necesario,downloadTask2()ya que es la mayor de las 3 tareas. Puedes ver esto en la siguiente captura de pantalla enToast messagefuente
launches para diversiones secuenciales , mientras queasyncpara concurrenteslaunchyasynccomenzarán nuevas corutinas. Usted está comparando una única corutina sin hijos con una única con 3 niños. Puede reemplazar cada una de lasasyncinvocacioneslaunchy absolutamente nada cambiaría con respecto a la concurrencia.ambos constructores de coroutine, es decir, launch y async, son básicamente lambdas con un receptor de tipo CoroutineScope, lo que significa que su bloque interno se compila como una función de suspensión, por lo tanto, ambos se ejecutan en modo asíncrono Y ambos ejecutarán su bloque secuencialmente.
La diferencia entre el lanzamiento y el asíncrono es que permiten dos posibilidades diferentes. El generador de inicio devuelve un trabajo, sin embargo, la función asíncrona devolverá un objeto diferido. Puede usar el lanzamiento para ejecutar un bloque del que no espera ningún valor devuelto, es decir, escribir en una base de datos o guardar un archivo o procesar algo que básicamente solo llama su efecto secundario. Por otro lado, async que devuelve un diferido como dije anteriormente devuelve un valor útil de la ejecución de su bloque, un objeto que envuelve sus datos, por lo que puede usarlo principalmente para su resultado, pero posiblemente también para su efecto secundario. NB: puede quitar el diferido y obtener su valor utilizando la función esperar, que bloqueará la ejecución de sus declaraciones hasta que se devuelva un valor o se generen excepciones.
Ambos creadores de rutina (lanzamiento y asíncrono) son cancelables.
¿algo más ?: sí con el lanzamiento si se lanza una excepción dentro de su bloque, la rutina se cancela automáticamente y se entregan las excepciones. Por otro lado, si eso sucede con asíncrono, la excepción no se propaga más y debe capturarse / manejarse dentro del objeto diferido devuelto.
más sobre las rutinas https://kotlinlang.org/docs/tutorials/coroutines/coroutines-basic-jvm.html https://www.codementor.io/blog/kotlin-coroutines-6n53p8cbn1
fuente
lanzamiento devuelve un trabajo
async devuelve un resultado (trabajo diferido)
launch with join se usa para esperar hasta que el trabajo termine. Simplemente suspende la rutina que llama a join (), dejando el hilo actual libre para realizar otro trabajo (como ejecutar otra rutina) mientras tanto.
async se usa para calcular algunos resultados. Crea una rutina y devuelve su resultado futuro como una implementación de Diferido. La rutina en ejecución se cancela cuando se cancela el aplazamiento resultante.
Considere un método asíncrono que devuelve un valor de cadena. Si el método asíncrono se usa sin esperar, devolverá una cadena diferida, pero si se usa esperar, obtendrá una cadena como resultado
La diferencia clave entre asíncrono y lanzamiento. Diferido devuelve un valor particular de tipo T después de que su Coroutine termina de ejecutarse, mientras que Job no lo hace.
fuente
Async vs Launch Async vs Launch Diff Image
lanzamiento / asíncrono sin resultado
asíncrono para el resultado
fuente