SlideShare uma empresa Scribd logo
1 de 31
Coroutines:
O que são, como funcionam e como utilizá-las
Paulo Sato • Master Engineer • psato@ciandt.com
Paulo Sato
Desenvolvedor Android há 10 anos
Está com a CI&T há 3 anos
Gosto de ensinar pessoas e adoro aprender
coisas novas!
linkedin.com/in/paulovsato
Introdução a
Coroutines
Mas afinal, o que é uma Coroutine?
Coroutine
● São rotinas cooperativas, ou seja, rotinas (funções, métodos,
procedimentos) que concordam em parar sua execução,
permitindo que outra rotina possa ser executada naquele
momento e esperando que essa rotina secundária devolva a
execução para ela em algum momento
● Dessa forma, uma rotina coopera com a outra
● Criada para dar a sensação de execução paralela em sistemas com um
processador e apenas uma thread
Coroutine
Kotlin
Coroutines
Suspend Functions
● No Kotlin, para uma função poder parar no meio, não precisamos
mais chamar o yield (que é uma Suspend Function); qualquer
chamada para uma Suspend Function pode parar a execução de
uma Coroutine
● Funcionam utilizando Continuations para guardar o estado da
execução
Código Kotlin
interface ShowRepository {
@Throws(IOException::class)
suspend fun searchShow(query: String):
List<ShowInfo>
@Throws(IOException::class)
suspend fun showRating(id: String): Rating
}
@Metadata
public interface ShowRepository {
@Nullable
Object searchShow(@NotNull String var1, @NotNull Continuation var2)
throws IOException;
@Nullable
Object showRating(@NotNull String var1, @NotNull Continuation var2)
throws IOException;
}
Código gerado
Coroutine Context
● Coroutines sempre são executadas em um contexto representado
pelo valor da CoroutineContext, que é definido na própria
biblioteca
● O contexto das Coroutines pode ser pensado como um
agrupamento de alguns elementos. Os principais elementos são
o Job e o Dispatcher
Job
● Conceitualmente, um trabalho é algo cancelável com um ciclo de
vida que culmina em sua completude
● Toda Coroutine roda em um Job. Você pode especificar um ou
um novo será criado quando uma nova Coroutine for lançada. O
Job é utilizado principalmente para fazer a junção de Coroutines
e cancelamentos
Dispatcher
● O CoroutineDispatcher determina qual thread, ou threads, que a
Coroutine utiliza para sua execução. O Dispatcher pode confinar
a execução a uma Thread específica, disparar a um ThreadPool,
ou deixar ela rodar sem confinamento (que normalmente não é
utilizado)
● Dispatcher.Default: Utiliza um pool comum de thread. Deve ser utilizado para tarefas
com computação intensiva
● Dispatcher.IO: Utiliza um pool compartilhado de thread criado sob demanda, que foi
feito para operações bloqueantes
● Dispatcher.Main: Apenas para Android, serve para executar a Coroutine na main thread
(atualizar UI)
Launch
● Lança uma nova Coroutine, sem bloquear a thread atual.
Retornando um Job, a Coroutine será cancelada quando um Job
for cancelado
Exemplo - Launch
val request = launch {
// it spawns two other jobs, one with GlobalScope
GlobalScope.launch {
}
// and the other inherits the parent context
launch {
}
}
delay(500)
request.cancel() // cancel processing of the request
delay(1000) // delay a second to see what happens
println("main: Who has survived request cancellation?")
delay(100)
println("job2: I am a child of the request coroutine")
delay(1000)
println("job2: I will not execute this line if my parent request is cancelled")
println("job1: I run in GlobalScope and execute independently!")
delay(1000)
println("job1: I am not affected by cancellation of the request")
Resultado
job1: I run in GlobalScope and execute independently!
job2: I am a child of the request coroutine
job1: I am not affected by cancellation of the request
main: Who has survived request cancellation?
withContext
● Chama um bloco de código com o contexto passado como
parâmetro, suspendendo a execução atual até que o bloco
complete sua execução e retorne seu resultado
● Muito utilizado em Android para executar operações em
background e atualizar a UI com o resultado
Exemplo - withContext
parentJob = CoroutineScope(Dispatchers.Main + exceptionHandler).launch {
val result = withContext(Dispatchers.IO) {
executeOnBackground(request)
}
response(result)
}
Async
● Cria uma Coroutine e retorna o futuro resultado como um
Deferred. A Coroutine que está rodando será cancelada caso o
resultado do Deferred seja cancelado
● A Coroutine gerada no Async tem uma diferença chave
comparada com outras primitivas em outras linguagens e
frameworks: ela cancela o Job pai em falha para garantir um
paradigma estruturado de concorrência
Exemplo - Async
log("Started main coroutine")
// run two background value computations
val v1 = async(CoroutineName("v1coroutine")) {
}
val v2 = async(CoroutineName("v2coroutine")) {
}
log("The answer for v1 / v2 = ${v1.await() / }")
delay(500)
log("Computing v1")
252
delay(1000)
log("Computing v2")
6
v2.await()
Resultado
[main @main#1] Started main coroutine
[main @v1coroutine#2] Computing v1
[main @v2coroutine#3] Computing v2
[main @main#1] The answer for v1 / v2 = 42
Deferred
● O Deferred<T> é uma classe genérica que representa uma
promessa de entregar um resultado no futuro. É necessário
chamar a suspend function await no objeto deferred para
conseguir o resultado eventualmente.
● A classe Deferred estende a class Job, portanto pode ser
utilizada para cancelar a Courtines filhas.
Sincronização
Synchronized
● Synchronized não funciona em
todos os casos para Coroutines
Exemplo - Synchronized
fun main() = runBlocking<Unit> {
launch {
val result1 = async {
dosomething(1)
}
val result2 = async {
dosomething(2)
}
result1.await()
result2.await()
println("main: finished")
}
}
@Synchronized suspend fun dosomething(thread : Int){
println("Start synchronized block $thread ")
for(i in 0..5){
delay(100)
println("step synchronized block $thread")
}
println("End synchronized block $thread")
}
Resultado
Start synchronized block 1
Start synchronized block 2
step synchronized block 1
step synchronized block 2
step synchronized block 1
step synchronized block 2
step synchronized block 1
step synchronized block 2
step synchronized block 1
step synchronized block 2
step synchronized block 1
step synchronized block 2
step synchronized block 1
End synchronized block 1
step synchronized block 2
End synchronized block 2
main: finished
Mutex
● Exclusão mútua para Coroutines
● Mutex tem dois estados: trancado e aberto
● É não reentrante; isso significa que chamar o lock da mesma
thread/Coroutine que atualmente tem a chave ainda faz com que
o invocante fique suspendido
Exemplo - Mutex
val mutex = Mutex(false)
fun main() = runBlocking<Unit> {
launch {
val result1 = async {
dosomething(1)
}
val result2 = async {
dosomething(2)
}
result1.await()
result2.await()
println("main: finished")
}
}
suspend fun dosomething(thread : Int){
mutex.lock()
println("Start synchronized block $thread ")
for(i in 0..5){
delay(100)
println("step synchronized block $thread")
}
println("End synchronized block $thread")
mutex.unlock()
}
Resultado
Start synchronized block 1
step synchronized block 1
step synchronized block 1
step synchronized block 1
step synchronized block 1
step synchronized block 1
step synchronized block 1
End synchronized block 1
Start synchronized block 2
step synchronized block 2
step synchronized block 2
step synchronized block 2
step synchronized block 2
step synchronized block 2
step synchronized block 2
End synchronized block 2
main: finished
● Um Channel é conceitualmente similar a uma BlockingQueue.
Duas diferenças chave entre eles:
● Ao invés da operação bloqueante put, ele tem a operação send, que suspende a
Coroutine
● Ao invés da operação bloqueante take, ele tem o receive, que suspende a
Coroutine
● É possível implementar back pressure para Coroutines com
Pipelines (Channels que podem emitir infinitos valores)
Channels
Code - Pipeline
fun main() = runBlocking {
val numbers = produceNumbers() // produces integers from 1 and on
val squares = square(numbers) // squares integers
for (i in 1..5) println(squares.receive()) // print first five
}
fun CoroutineScope.produceNumbers() = produce<Int> {
}
fun CoroutineScope.square(numbers: ReceiveChannel<Int>):
ReceiveChannel<Int> = produce {
}
1
4
9
16
25
Done!var x = 1
while (true) send(x++) // infinite stream of integers starting from 1
delay(1000)
for (x in numbers) send(x * x)
println("Done!") // we are done
coroutineContext.cancelChildren() // cancel children coroutines
Obrigado!
linkedin.com/in/paulovsato
Paulo Sato
psato@ciandt.com@impaulosato

Mais conteúdo relacionado

Mais procurados

Threads 04 Variáveis atômicas
Threads 04 Variáveis atômicasThreads 04 Variáveis atômicas
Threads 04 Variáveis atômicasHelder da Rocha
 
Utilitários para Programação Concorrente em Java (2005)
Utilitários para Programação Concorrente em Java (2005)Utilitários para Programação Concorrente em Java (2005)
Utilitários para Programação Concorrente em Java (2005)Helder da Rocha
 
Threads 07: Sincronizadores
Threads 07: SincronizadoresThreads 07: Sincronizadores
Threads 07: SincronizadoresHelder da Rocha
 
Threads 06: Coleções concorrentes
Threads 06: Coleções concorrentesThreads 06: Coleções concorrentes
Threads 06: Coleções concorrentesHelder da Rocha
 
Programação Paralela - Threads
Programação Paralela - ThreadsProgramação Paralela - Threads
Programação Paralela - ThreadsGlaucio Scheibel
 
[Curso Java Basico] Aula 74: Threads: deadlocks
[Curso Java Basico] Aula 74: Threads: deadlocks[Curso Java Basico] Aula 74: Threads: deadlocks
[Curso Java Basico] Aula 74: Threads: deadlocksLoiane Groner
 
Node.js - #5 - Process - Rodrigo Branas
Node.js - #5 - Process - Rodrigo BranasNode.js - #5 - Process - Rodrigo Branas
Node.js - #5 - Process - Rodrigo BranasRodrigo Branas
 
Curso Java Basico] Aula 67: Criando Threads + metodos start, run e sleep
Curso Java Basico] Aula 67: Criando Threads + metodos start, run e sleepCurso Java Basico] Aula 67: Criando Threads + metodos start, run e sleep
Curso Java Basico] Aula 67: Criando Threads + metodos start, run e sleepLoiane Groner
 
[Curso Java Basico] Aula 71: Threads: metodos e blocos sincronizados (synchro...
[Curso Java Basico] Aula 71: Threads: metodos e blocos sincronizados (synchro...[Curso Java Basico] Aula 71: Threads: metodos e blocos sincronizados (synchro...
[Curso Java Basico] Aula 71: Threads: metodos e blocos sincronizados (synchro...Loiane Groner
 
Node.js - #2 - Sistema de Módulos - Rodrigo Branas
Node.js - #2 - Sistema de Módulos - Rodrigo BranasNode.js - #2 - Sistema de Módulos - Rodrigo Branas
Node.js - #2 - Sistema de Módulos - Rodrigo BranasRodrigo Branas
 
[Curso Java Basico] Aula 68: Threads: Interface Runnable
[Curso Java Basico] Aula 68: Threads: Interface Runnable[Curso Java Basico] Aula 68: Threads: Interface Runnable
[Curso Java Basico] Aula 68: Threads: Interface RunnableLoiane Groner
 
Node.js - #3 - Global Objects - Rodrigo Branas
Node.js - #3 - Global Objects - Rodrigo BranasNode.js - #3 - Global Objects - Rodrigo Branas
Node.js - #3 - Global Objects - Rodrigo BranasRodrigo Branas
 
Node.js - #4 - Timers - Rodrigo Branas
Node.js - #4 - Timers - Rodrigo BranasNode.js - #4 - Timers - Rodrigo Branas
Node.js - #4 - Timers - Rodrigo BranasRodrigo Branas
 
Workshop React Hooks
Workshop React HooksWorkshop React Hooks
Workshop React HooksDan Vitoriano
 
Android carregando dados com loaders
Android   carregando dados com loadersAndroid   carregando dados com loaders
Android carregando dados com loadersFernando Camargo
 
Opennebula Introdução
Opennebula IntroduçãoOpennebula Introdução
Opennebula IntroduçãoLuís Eduardo
 

Mais procurados (20)

Threads 04 Variáveis atômicas
Threads 04 Variáveis atômicasThreads 04 Variáveis atômicas
Threads 04 Variáveis atômicas
 
Threads
ThreadsThreads
Threads
 
Utilitários para Programação Concorrente em Java (2005)
Utilitários para Programação Concorrente em Java (2005)Utilitários para Programação Concorrente em Java (2005)
Utilitários para Programação Concorrente em Java (2005)
 
Threads 07: Sincronizadores
Threads 07: SincronizadoresThreads 07: Sincronizadores
Threads 07: Sincronizadores
 
Threads 06: Coleções concorrentes
Threads 06: Coleções concorrentesThreads 06: Coleções concorrentes
Threads 06: Coleções concorrentes
 
Programação Paralela - Threads
Programação Paralela - ThreadsProgramação Paralela - Threads
Programação Paralela - Threads
 
[Curso Java Basico] Aula 74: Threads: deadlocks
[Curso Java Basico] Aula 74: Threads: deadlocks[Curso Java Basico] Aula 74: Threads: deadlocks
[Curso Java Basico] Aula 74: Threads: deadlocks
 
Node.js - #5 - Process - Rodrigo Branas
Node.js - #5 - Process - Rodrigo BranasNode.js - #5 - Process - Rodrigo Branas
Node.js - #5 - Process - Rodrigo Branas
 
Curso Java Basico] Aula 67: Criando Threads + metodos start, run e sleep
Curso Java Basico] Aula 67: Criando Threads + metodos start, run e sleepCurso Java Basico] Aula 67: Criando Threads + metodos start, run e sleep
Curso Java Basico] Aula 67: Criando Threads + metodos start, run e sleep
 
[Curso Java Basico] Aula 71: Threads: metodos e blocos sincronizados (synchro...
[Curso Java Basico] Aula 71: Threads: metodos e blocos sincronizados (synchro...[Curso Java Basico] Aula 71: Threads: metodos e blocos sincronizados (synchro...
[Curso Java Basico] Aula 71: Threads: metodos e blocos sincronizados (synchro...
 
Node.js - #2 - Sistema de Módulos - Rodrigo Branas
Node.js - #2 - Sistema de Módulos - Rodrigo BranasNode.js - #2 - Sistema de Módulos - Rodrigo Branas
Node.js - #2 - Sistema de Módulos - Rodrigo Branas
 
[Curso Java Basico] Aula 68: Threads: Interface Runnable
[Curso Java Basico] Aula 68: Threads: Interface Runnable[Curso Java Basico] Aula 68: Threads: Interface Runnable
[Curso Java Basico] Aula 68: Threads: Interface Runnable
 
Node.js - #3 - Global Objects - Rodrigo Branas
Node.js - #3 - Global Objects - Rodrigo BranasNode.js - #3 - Global Objects - Rodrigo Branas
Node.js - #3 - Global Objects - Rodrigo Branas
 
Consegi 2011: Puppet
Consegi 2011: PuppetConsegi 2011: Puppet
Consegi 2011: Puppet
 
12 threads
12 threads12 threads
12 threads
 
Node.js - #4 - Timers - Rodrigo Branas
Node.js - #4 - Timers - Rodrigo BranasNode.js - #4 - Timers - Rodrigo Branas
Node.js - #4 - Timers - Rodrigo Branas
 
Workshop React Hooks
Workshop React HooksWorkshop React Hooks
Workshop React Hooks
 
Android carregando dados com loaders
Android   carregando dados com loadersAndroid   carregando dados com loaders
Android carregando dados com loaders
 
Opennebula Introdução
Opennebula IntroduçãoOpennebula Introdução
Opennebula Introdução
 
Threads e sockets java
Threads e sockets javaThreads e sockets java
Threads e sockets java
 

Semelhante a Coroutines Kotlin

Codando Assíncrono com Coroutines
Codando Assíncrono com CoroutinesCodando Assíncrono com Coroutines
Codando Assíncrono com CoroutinesArildo Borges Jr
 
Definição de processos
Definição de processosDefinição de processos
Definição de processosRodrigo Almeida
 
Coroutine e concorrência python
Coroutine e concorrência   python Coroutine e concorrência   python
Coroutine e concorrência python Kaueh Moreno
 
Async/Await Pattern in C#
Async/Await Pattern in C#Async/Await Pattern in C#
Async/Await Pattern in C#Leandro Silva
 
Servlets 3: o contexto assíncrono - JavaOne 2010 - Paulo Silveira
Servlets 3: o contexto assíncrono - JavaOne 2010 - Paulo SilveiraServlets 3: o contexto assíncrono - JavaOne 2010 - Paulo Silveira
Servlets 3: o contexto assíncrono - JavaOne 2010 - Paulo SilveiraCaelum
 
Introdução ao processamento paralelo com o Grand Central Dispatch
Introdução ao processamento paralelo com o Grand Central DispatchIntrodução ao processamento paralelo com o Grand Central Dispatch
Introdução ao processamento paralelo com o Grand Central Dispatchflisolmaringa
 
Regiões críticas dos Sistemas Operacionais
Regiões críticas dos Sistemas OperacionaisRegiões críticas dos Sistemas Operacionais
Regiões críticas dos Sistemas OperacionaisAbadia Cardoso
 
Arquitetura de Computadores: Processos e Threads
Arquitetura de Computadores: Processos e ThreadsArquitetura de Computadores: Processos e Threads
Arquitetura de Computadores: Processos e ThreadsEvandro Júnior
 
Programação Concorrente - Aula 04
Programação Concorrente - Aula 04Programação Concorrente - Aula 04
Programação Concorrente - Aula 04thomasdacosta
 
Kernel com requisitos temporais
Kernel com requisitos temporaisKernel com requisitos temporais
Kernel com requisitos temporaisRodrigo Almeida
 

Semelhante a Coroutines Kotlin (20)

Codando Assíncrono com Coroutines
Codando Assíncrono com CoroutinesCodando Assíncrono com Coroutines
Codando Assíncrono com Coroutines
 
Definição de processos
Definição de processosDefinição de processos
Definição de processos
 
Coroutine e concorrência python
Coroutine e concorrência   python Coroutine e concorrência   python
Coroutine e concorrência python
 
Async/Await Pattern in C#
Async/Await Pattern in C#Async/Await Pattern in C#
Async/Await Pattern in C#
 
Criando Aplicações Resilientes
Criando Aplicações ResilientesCriando Aplicações Resilientes
Criando Aplicações Resilientes
 
Servlets 3: o contexto assíncrono - JavaOne 2010 - Paulo Silveira
Servlets 3: o contexto assíncrono - JavaOne 2010 - Paulo SilveiraServlets 3: o contexto assíncrono - JavaOne 2010 - Paulo Silveira
Servlets 3: o contexto assíncrono - JavaOne 2010 - Paulo Silveira
 
Processos
ProcessosProcessos
Processos
 
Kernel cooperativo
Kernel cooperativoKernel cooperativo
Kernel cooperativo
 
Igor Oliveira - Puppet
Igor Oliveira - PuppetIgor Oliveira - Puppet
Igor Oliveira - Puppet
 
PHP fora da Web
PHP fora da WebPHP fora da Web
PHP fora da Web
 
Aula1
Aula1Aula1
Aula1
 
Introdução ao processamento paralelo com o Grand Central Dispatch
Introdução ao processamento paralelo com o Grand Central DispatchIntrodução ao processamento paralelo com o Grand Central Dispatch
Introdução ao processamento paralelo com o Grand Central Dispatch
 
Regiões críticas dos Sistemas Operacionais
Regiões críticas dos Sistemas OperacionaisRegiões críticas dos Sistemas Operacionais
Regiões críticas dos Sistemas Operacionais
 
Arquitetura de Computadores: Processos e Threads
Arquitetura de Computadores: Processos e ThreadsArquitetura de Computadores: Processos e Threads
Arquitetura de Computadores: Processos e Threads
 
Programação Concorrente - Aula 04
Programação Concorrente - Aula 04Programação Concorrente - Aula 04
Programação Concorrente - Aula 04
 
Kernel com requisitos temporais
Kernel com requisitos temporaisKernel com requisitos temporais
Kernel com requisitos temporais
 
Threads em java
Threads em javaThreads em java
Threads em java
 
Aula java[1]
Aula java[1]Aula java[1]
Aula java[1]
 
Introdução à OpenGL
Introdução à OpenGLIntrodução à OpenGL
Introdução à OpenGL
 
Java 13
Java 13Java 13
Java 13
 

Coroutines Kotlin

  • 1. Coroutines: O que são, como funcionam e como utilizá-las Paulo Sato • Master Engineer • psato@ciandt.com
  • 2. Paulo Sato Desenvolvedor Android há 10 anos Está com a CI&T há 3 anos Gosto de ensinar pessoas e adoro aprender coisas novas! linkedin.com/in/paulovsato
  • 4. Mas afinal, o que é uma Coroutine?
  • 5. Coroutine ● São rotinas cooperativas, ou seja, rotinas (funções, métodos, procedimentos) que concordam em parar sua execução, permitindo que outra rotina possa ser executada naquele momento e esperando que essa rotina secundária devolva a execução para ela em algum momento ● Dessa forma, uma rotina coopera com a outra ● Criada para dar a sensação de execução paralela em sistemas com um processador e apenas uma thread
  • 8. Suspend Functions ● No Kotlin, para uma função poder parar no meio, não precisamos mais chamar o yield (que é uma Suspend Function); qualquer chamada para uma Suspend Function pode parar a execução de uma Coroutine ● Funcionam utilizando Continuations para guardar o estado da execução
  • 9. Código Kotlin interface ShowRepository { @Throws(IOException::class) suspend fun searchShow(query: String): List<ShowInfo> @Throws(IOException::class) suspend fun showRating(id: String): Rating } @Metadata public interface ShowRepository { @Nullable Object searchShow(@NotNull String var1, @NotNull Continuation var2) throws IOException; @Nullable Object showRating(@NotNull String var1, @NotNull Continuation var2) throws IOException; } Código gerado
  • 10. Coroutine Context ● Coroutines sempre são executadas em um contexto representado pelo valor da CoroutineContext, que é definido na própria biblioteca ● O contexto das Coroutines pode ser pensado como um agrupamento de alguns elementos. Os principais elementos são o Job e o Dispatcher
  • 11. Job ● Conceitualmente, um trabalho é algo cancelável com um ciclo de vida que culmina em sua completude ● Toda Coroutine roda em um Job. Você pode especificar um ou um novo será criado quando uma nova Coroutine for lançada. O Job é utilizado principalmente para fazer a junção de Coroutines e cancelamentos
  • 12. Dispatcher ● O CoroutineDispatcher determina qual thread, ou threads, que a Coroutine utiliza para sua execução. O Dispatcher pode confinar a execução a uma Thread específica, disparar a um ThreadPool, ou deixar ela rodar sem confinamento (que normalmente não é utilizado) ● Dispatcher.Default: Utiliza um pool comum de thread. Deve ser utilizado para tarefas com computação intensiva ● Dispatcher.IO: Utiliza um pool compartilhado de thread criado sob demanda, que foi feito para operações bloqueantes ● Dispatcher.Main: Apenas para Android, serve para executar a Coroutine na main thread (atualizar UI)
  • 13. Launch ● Lança uma nova Coroutine, sem bloquear a thread atual. Retornando um Job, a Coroutine será cancelada quando um Job for cancelado
  • 14. Exemplo - Launch val request = launch { // it spawns two other jobs, one with GlobalScope GlobalScope.launch { } // and the other inherits the parent context launch { } } delay(500) request.cancel() // cancel processing of the request delay(1000) // delay a second to see what happens println("main: Who has survived request cancellation?") delay(100) println("job2: I am a child of the request coroutine") delay(1000) println("job2: I will not execute this line if my parent request is cancelled") println("job1: I run in GlobalScope and execute independently!") delay(1000) println("job1: I am not affected by cancellation of the request")
  • 15. Resultado job1: I run in GlobalScope and execute independently! job2: I am a child of the request coroutine job1: I am not affected by cancellation of the request main: Who has survived request cancellation?
  • 16. withContext ● Chama um bloco de código com o contexto passado como parâmetro, suspendendo a execução atual até que o bloco complete sua execução e retorne seu resultado ● Muito utilizado em Android para executar operações em background e atualizar a UI com o resultado
  • 17. Exemplo - withContext parentJob = CoroutineScope(Dispatchers.Main + exceptionHandler).launch { val result = withContext(Dispatchers.IO) { executeOnBackground(request) } response(result) }
  • 18. Async ● Cria uma Coroutine e retorna o futuro resultado como um Deferred. A Coroutine que está rodando será cancelada caso o resultado do Deferred seja cancelado ● A Coroutine gerada no Async tem uma diferença chave comparada com outras primitivas em outras linguagens e frameworks: ela cancela o Job pai em falha para garantir um paradigma estruturado de concorrência
  • 19. Exemplo - Async log("Started main coroutine") // run two background value computations val v1 = async(CoroutineName("v1coroutine")) { } val v2 = async(CoroutineName("v2coroutine")) { } log("The answer for v1 / v2 = ${v1.await() / }") delay(500) log("Computing v1") 252 delay(1000) log("Computing v2") 6 v2.await()
  • 20. Resultado [main @main#1] Started main coroutine [main @v1coroutine#2] Computing v1 [main @v2coroutine#3] Computing v2 [main @main#1] The answer for v1 / v2 = 42
  • 21. Deferred ● O Deferred<T> é uma classe genérica que representa uma promessa de entregar um resultado no futuro. É necessário chamar a suspend function await no objeto deferred para conseguir o resultado eventualmente. ● A classe Deferred estende a class Job, portanto pode ser utilizada para cancelar a Courtines filhas.
  • 23. Synchronized ● Synchronized não funciona em todos os casos para Coroutines
  • 24. Exemplo - Synchronized fun main() = runBlocking<Unit> { launch { val result1 = async { dosomething(1) } val result2 = async { dosomething(2) } result1.await() result2.await() println("main: finished") } } @Synchronized suspend fun dosomething(thread : Int){ println("Start synchronized block $thread ") for(i in 0..5){ delay(100) println("step synchronized block $thread") } println("End synchronized block $thread") }
  • 25. Resultado Start synchronized block 1 Start synchronized block 2 step synchronized block 1 step synchronized block 2 step synchronized block 1 step synchronized block 2 step synchronized block 1 step synchronized block 2 step synchronized block 1 step synchronized block 2 step synchronized block 1 step synchronized block 2 step synchronized block 1 End synchronized block 1 step synchronized block 2 End synchronized block 2 main: finished
  • 26. Mutex ● Exclusão mútua para Coroutines ● Mutex tem dois estados: trancado e aberto ● É não reentrante; isso significa que chamar o lock da mesma thread/Coroutine que atualmente tem a chave ainda faz com que o invocante fique suspendido
  • 27. Exemplo - Mutex val mutex = Mutex(false) fun main() = runBlocking<Unit> { launch { val result1 = async { dosomething(1) } val result2 = async { dosomething(2) } result1.await() result2.await() println("main: finished") } } suspend fun dosomething(thread : Int){ mutex.lock() println("Start synchronized block $thread ") for(i in 0..5){ delay(100) println("step synchronized block $thread") } println("End synchronized block $thread") mutex.unlock() }
  • 28. Resultado Start synchronized block 1 step synchronized block 1 step synchronized block 1 step synchronized block 1 step synchronized block 1 step synchronized block 1 step synchronized block 1 End synchronized block 1 Start synchronized block 2 step synchronized block 2 step synchronized block 2 step synchronized block 2 step synchronized block 2 step synchronized block 2 step synchronized block 2 End synchronized block 2 main: finished
  • 29. ● Um Channel é conceitualmente similar a uma BlockingQueue. Duas diferenças chave entre eles: ● Ao invés da operação bloqueante put, ele tem a operação send, que suspende a Coroutine ● Ao invés da operação bloqueante take, ele tem o receive, que suspende a Coroutine ● É possível implementar back pressure para Coroutines com Pipelines (Channels que podem emitir infinitos valores) Channels
  • 30. Code - Pipeline fun main() = runBlocking { val numbers = produceNumbers() // produces integers from 1 and on val squares = square(numbers) // squares integers for (i in 1..5) println(squares.receive()) // print first five } fun CoroutineScope.produceNumbers() = produce<Int> { } fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce { } 1 4 9 16 25 Done!var x = 1 while (true) send(x++) // infinite stream of integers starting from 1 delay(1000) for (x in numbers) send(x * x) println("Done!") // we are done coroutineContext.cancelChildren() // cancel children coroutines