[Coroutine] Generadores de rutinas y trabajos.Range Builder | Por Daewon Kwon | Marzo de 2022
runBlocking
en this
puede ver que la rutina es el objeto receptor (Receptor).
→ «coroutine#1»: BlockingCoroutine{Activo}@36d64342
Recibir object = también se denomina extender lambda y se puede usar como extender lambda.
Usa el concepto de bloques de código como si fueran rutinas extendidas.
Si solo lo inicia, se ejecutará en el subproceso principal, pero launch.(Dispatchers.Default) se ejecutará en otro subproceso utilizando el despachador predeterminado.
Ejemplo 15
En realidad no fue cancelado. El trabajo1 que creamos es un código que no entiende cancelar.
Retardo de retorno asíncrono.
Diferido significa literalmente aplazar, lo que significa «posponer la recepción de resultados».
Deferred es una interfaz que amplía Job sin un valor de resultado para realizar operaciones asincrónicas con un resultado. Es decir, un Diferido es un Trabajo, por lo que un Diferido tiene todas las propiedades de un Trabajo. Las variables de estado del trabajo (isActive, isCancelled, isCompleted) y el manejo de excepciones se pueden aplicar igualmente en Deferred.
Para recibir el valor del resultado de Deferred, utilice la función await() en la interfaz de Deferred. Al llamar a await() en el código, la rutina que ejecuta la función main() se suspende hasta que se recibe el resultado diferido del subproceso IO.
Los retrasos se pueden crear utilizando bloques asincrónicos coroutine.
suspend fun main() {
val deferred : Deferred= val deferredResult = deferred.await() println(deferredResult)
CoroutineScope(Dispatchers.IO).async {
"Deferred Result"
}
}
La diferencia entre Deferred y Jobd es que, a diferencia de Job, las excepciones se propagan automáticamente, Deferred no propaga las excepciones automáticamente. Esto se debe a que Deferred debe esperar para recibir el valor del resultado. Deferred debe usar await(), que es el método de recepción, espera el valor del resultado y propaga la excepción.
suspend fun main() {
val exceptionHandler = CoroutineExceptionHandler { _, exception ->
when (exception) {
is IllegalArgumentException -> println("More Argument Needed To Process Job")
is InterruptedException -> println("Job Interrupted")
}
} val deferred = CoroutineScope(Dispatchers.IO).async(exceptionHandler) {
throw IllegalArgumentException()
arrayOf(1, 2, 3)
} delay(1000)
}
El código anterior no genera nada. El motivo es que Deferred no propaga los errores automáticamente. Un Diferido es una variable que recibe un valor en algún momento en el futuro, porque no hay necesidad de propagar errores en los casos en que el valor no es necesario.
Por lo tanto, incluso si se agrega await(), el error se propagará al subproceso principal, en lugar de manejar el error en ExceptionHandler, el subproceso principal se cerrará a la fuerza debido al error. Por lo tanto, el mensaje «el trabajo de procesamiento requiere más argumentos» no aparece cuando se produce una ArgumentException ilegal.
Entonces, ¿cómo puedo cambiarlo para que CoroutineExceptionHandling funcione?
Simplemente agregue un CoroutineExceptionHanlder donde se propaga el error. Es decir, de forma asíncrona, CoroutineExceptionhandler debe agregarse a la ubicación de recepción sin necesidad de un CoroutineExceptionHanlder independiente.
suspend fun main() { val exceptionHandler = CoroutineExceptionHandler { _, exception ->
when (exception) {
is IllegalArgumentException -> println("More Argument Needed To Process Job")
is InterruptedException -> println("Job Interrupted")
}
} val deferred = CoroutineScope(Dispatchers.IO).async {
throw IllegalArgumentException()
arrayOf(1, 2, 3)
} CoroutineScope(Dispatchers.IO).launch(SupervisorJob() + exceptionHandler) {
deferred.await()
}.join()
}
Si observa el último bloque del código anterior, puede ver que la excepción se maneja configurando un controlador de excepción en el subproceso IO y recibiendo el valor del resultado diferido dentro del bloque. La razón para usar join() es asegurar que el subproceso principal no finalice hasta que se complete la tarea correspondiente.
GlobalScope
No pertenece a ningún tier y tiene el problema de ejecutarse eternamente. Al igual que la programación no hace un buen uso de los objetos globales. GlobalScope
Tampoco funciona.
GlobalScope
El formato más recomendado es CoroutineScope
es usar CoroutineScope
es el argumento CoroutineContext
puede colocar un elemento de rutina o, como aprendimos anteriormente, puede combinar elementos para crear un contexto de rutina.
La forma más sistemática de manejar las excepciones es usar controladores de excepciones coroutine (CEH).
Aprendí cómo manejar las excepciones sistemáticamente a través de SupervisorJob y CEH, pero dado que varios subprocesos utilizan corrutinas, habrá problemas de concurrencia.Aprenda a manejar sistemáticamente los objetos compartidos
Aunque el problema de visibilidad se resuelve con Volatile, la visibilidad puede ver correctamente el valor del contador mientras incrementa el valor. Pero puedo aumentarlo en otro hilo mientras lo aumento. Lo que estoy agregando es el incremento del valor anterior. volatile
Esto solo resuelve el problema de visibilidad, no el problema de leer y modificar al mismo tiempo.
AtomicInteger
Bueno para esta pregunta, pero no siempre la respuesta correcta.
incrementAndGet() incrementa el valor y devuelve el valor actual, lo que evita que otros subprocesos cambien el valor en el proceso. Por lo tanto, AtomicInteger se denomina estructura de datos segura para subprocesos.
Esto siempre conduce a la respuesta correcta, pero no siempre.
hilo limitado
newSingleThreadContext
Cree un hilo específico y use ese hilo.
Se crea un contexto de rutina, se crea un hilo específico y solo se usa ese hilo.
Garantizado para ejecutarse siempre en el mismo hilo.
Mutex es la abreviatura de exclusión mutua.
Permite el uso de secciones críticas al modificar el estado compartido y no permite el acceso simultáneo a las secciones críticas.
Actors es un concepto introducido por Carl Hewitt en 1973, que permite a los Actores poseer sus propios datos y acceder a esos datos solo a través de Actores, sin compartir esos datos con otras corrutinas.