Asynchronous Programming
- Técnica que permite que um programa não fique bloqueado numa operação potencialmente bloqueante;
- Em vez de esperar que a operação termine, o programa pode continuar a executar outras operações;
- O término da função pode ocorrer antes do término da operação.
Desvantagens
- Uma thread ocupa recursos, tanto em memória, quanto no CPU;
- Cenários thread per client ou thread per request não são escaláveis.
NIO2
- “New IO 2”;
- Permite realiza operações de IO assincronamente.
Callbacks
- Passar uma função como argumento de outra função, sendo invocada quando a operação terminar;
- A função retorna instantaneamente, sem esperar o fim da operação.
CompletionHandler<V, A>
- Handler para consumir o resultado de uma operação assíncrona;
- V: tipo resultante da execução da operação;
- Métodos:
completed(V result, A attachment): invocado quando a operação foi terminada com sucesso;failed(Throwable exc, A attachment): invocado quando a operação falhou.
AVISO: a execução síncrona de CompletionHandlers aninhados pode causar stack overflow, devido às reentrâncias.
NOTA: Thread Local Storage
- Forma de ter variáveis locais globais a uma thread;
- Variáveis do tipo ThreadLocal.
- Tem de se ter cuidado a utilizar este mecanismo, visto que outra computação pode ser executada na mesma thread e esta também tem acesso às variáveis.
Futures e Promises
- Representam uma operação;
- Permite obter o estado da operação e o seu resultado;
- Formas de sincronização com a operação:
- Polling -> “perguntar múltiplas vezes se já terminou”;
- Bloqueio com timeout;
- Ambas as ações acima descritas sõa bloqueantes, algo que não queremos na programação assíncrona, logo o tipo
CompletableFuturefornece uma terceira opção:
CompletableFuture
- Agendamento de uma continuação da operação, produzindo um novo CompletableFuture;
- Tem um funcionamento similar às Promises do Javascript;
- Como é possível observar, o flatMap retorna um Future de C (
F<C>) e não um Future de F( F<F<C>>); - Os erros não se perdem, propagam-se pelo pipeline de continuações.
- O método
geté bloqueante; - É compatível com a atribuição de um valor, com o método
complete; - O map é realizado pelo método
thenApplye o flatMap pelo métodothenCompose; - Estes métodos executam a continuação na chamada do
complete, ou seja, na thread que a completou; existe as variaçõesthenApplyAsyncethenComposeAsyncque executam a continuação numa thread de uma thread pool, que evita as reentrâncias.
Kotlin Coroutines
- Computações sequencias passíveis de suspensão;
- Não existe uma relação de 1-1 de computação por thread;
- Uma coroutine pode suspender a sua execução numa thread e retomar noutra;
- Podem ser vistas como light-weight threads.
Suspending Function
- Função que pode ser suspensa e retomada posteriormente;
- Keyword
suspend; - Só podem ser chamadas por outras suspending functions ou numa coroutine.
Concorrência Estruturada
- Novas coroutines só podem ser lançadas num
CoroutineScope, que delimita o tempo de vida de uma coroutine; - Um scope não termina até todas as coroutines dentro dele terminarem;
CoroutineScope
- Define o scope das coroutines;
- Todos os coroutine builders são extensão de CoroutineScope (à exceção de
runBlocking), e herdam automaticamente o contexto.
CoroutineContext
- Conjunto de elementos, usados para influenciar a execução de uma coroutine;
- Pode-se mudar o contexto de uma coroutine através do método
withContext.
Job
- Representa algo com um ciclo de vida, que pode ser cancelado ou concluído;
- Representa uma coroutine;
- Tem hierarquia “pais-filhos”;
- Quando um pai é cancelado, todos os filhos também o são;
- Quando um filho é cancelado, é lançada
CancellationException, que cancela o pai, e por consequente todos os filhos.
- Tem métodos como
cancelejoin; - Estados:
Funções relevantes
launch
- Coroutine builder;
- Lança uma nova coroutine concorrentemente com o resto do código.
runBlocking
- Coroutine builder;
- Bloqueia a thread onde é chamado;
- Cria um CoroutineScope;
- Thread bloqueada até todas as coroutines dentro do CoroutineScope terminarem.
delay
- Suspending function;
- Suspende a coroutine por um tempo especificado;
- Semelhante ao
Thread.sleep.
coroutineScope
- Fornece um CoroutineScope;
- Semelhante ao
runBlocking, só que não bloqueia a thread, apenas suspende; - Outra diferença é q é uma suspending function.
suspendCoroutine
- Obtém a continuação da mesma, e suspende a coroutine até esta ser retomada;
- Cria um ponto de suspensão;
Continuation.resumeeContinuation.resumeWithExceptionsão utilizadas para retomar a coroutine.
suspendCancellableCoroutine
- Suspende a coroutine como o método acima, mas fornecendo uma
CancellableContinuation; - Uma continuação é single-shot, significando que só é executada uma vez.