Aprimoramentos da API do Java 9 CompletableFuture

Aprimoramentos da API do Java 9 CompletableFuture

1. Introdução

Java 9 vem com algumas mudanças na classeCompletableFuture. Essas mudanças foram introduzidas como parte deJEP 266 para resolver reclamações e sugestões comuns desde sua introdução no JDK 8, mais especificamente, suporte para atrasos e tempos limite, melhor suporte para subclasses e alguns métodos de utilidade.

Em termos de código, a API vem com oito novos métodos e cinco novos métodos estáticos. Para habilitar essas adições, aproximadamente 1500 das 2400 linhas de código foram alteradas (conforme o Open JDK).

2. Adições de API de instância

Como mencionado, a API da instância vem com oito novas adições, são elas:

  1. Executor defaultExecutor ()

  2. CompletableFuture newIncompleteFuture ()

  3. CompletableFuture copy ()

  4. CompletionStage minimalCompletionStage ()

  5. CompletableFuture completeAsync (Fornecedor fornecedor, executor executor)

  6. CompletableFuture completeAsync (Fornecedor fornecedor)

  7. CompletableFuture ouTimeout (tempo limite longo, unidade TimeUnit)

  8. CompletableFuture completeOnTimeout (valor T, tempo limite longo, unidade TimeUnit)

2.1. MétododefaultExecutor()

Signature:Executor defaultExecutor()

Retorna oExecutor padrão usado para métodos assíncronos que não especificam umExecutor.

new CompletableFuture().defaultExecutor()

Isso pode ser substituído por subclasses retornando um executor fornecendo, pelo menos, um encadeamento independente.

2.2. MétodonewIncompleteFuture()

Signature:CompletableFuture<U> newIncompleteFuture()

OnewIncompleteFuture, também conhecido como “construtor virtual”, é usado para obter uma nova instância futura completável do mesmo tipo.

new CompletableFuture().newIncompleteFuture()

Este método é especialmente útil ao criar subclasses deCompletableFuture, principalmente porque é usado internamente em quase todos os métodos que retornam um novoCompletionStage, permitindo que as subclasses controlem qual subtipo é retornado por tais métodos.

2.3. Métodocopy()

Signature:CompletableFuture<T> copy()

Este método retorna um novoCompletableFuture que:

  • Quando isso é concluído normalmente, o novo é concluído normalmente também

  • Quando isso é concluído excepcionalmente com a exceção X, o novo também é concluído excepcionalmente com umCompletionException com X como causa

new CompletableFuture().copy()

Esse método pode ser útil como uma forma de “cópia defensiva”, para evitar que os clientes concluam, enquanto ainda podem organizar ações dependentes em uma instância específica deCompletableFuture.

2.4. MétodominimalCompletionStage()

Signature:CompletionStage<T> minimalCompletionStage()

Este método retorna um novoCompletionStage que se comporta exatamente da mesma maneira que o descrito pelo método de cópia, entretanto, tal nova instância lançaUnsupportedOperationException em cada tentativa de recuperar ou definir o valor resolvido.

new CompletableFuture().minimalCompletionStage()

Um novoCompletableFuture com todos os métodos disponíveis pode ser recuperado usando o métodotoCompletableFuture disponível na APICompletionStage.

2.5. MétodoscompleteAsync()

O métodocompleteAsync deve ser usado para completar oCompletableFuture assincronamente usando o valor dado peloSupplier fornecido.

Signatures:

CompletableFuture completeAsync(Supplier supplier, Executor executor)
CompletableFuture completeAsync(Supplier supplier)

A diferença entre esses dois métodos sobrecarregados é a existência do segundo argumento, onde oExecutor executando a tarefa pode ser especificado. Se nenhum for fornecido, o executor padrão (retornado pelo métododefaultExecutor) será usado.

2.6. MétodosorTimeout()

Signature:CompletableFuture<T> orTimeout(long timeout, TimeUnit unit)

new CompletableFuture().orTimeout(1, TimeUnit.SECONDS)

ResolveCompletableFuture excepcionalmente comTimeoutException, a menos que seja concluído antes do tempo limite especificado.

2.7. MétodocompleteOnTimeout()

Signature:CompletableFuture<T> completeOnTimeout(T value, long timeout, TimeUnit unit)

new CompletableFuture().completeOnTimeout(value, 1, TimeUnit.SECONDS)

ConcluiCompletableFuture normalmente com o valor especificado, a menos que seja concluído antes do tempo limite especificado.

3. Adições de API estática

Alguns métodos utilitários também foram adicionados. Eles são:

  1. Executor atrasadoExecutor (atraso longo, unidade TimeUnit, executor Executor)

  2. Executor atrasadoExecutor (atraso longo, unidade TimeUnit)

  3. CompletionStage completedStage (valor U)

  4. CompletionStage failedStage (ex lançável)

  5. CompletableFuture failedFuture (ex lançável)

3.1. MétodosdelayedExecutor

Signatures:

Executor delayedExecutor(long delay, TimeUnit unit, Executor executor)
Executor delayedExecutor(long delay, TimeUnit unit)

Retorna um novoExecutor que submete uma tarefa ao executor base fornecido após o atraso fornecido (ou nenhum atraso se não for positivo). Cada atraso começa na invocação do método de execução do executor retornado. Se nenhum executor for especificado, o executor padrão (ForkJoinPool.commonPool()) será usado.

3.2. MétodoscompletedStage efailedStage

Signatures:

 CompletionStage completedStage(U value)
 CompletionStage failedStage(Throwable ex)

Os métodos deste utilitário retornam instânciasCompletionStage já resolvidas, concluídas normalmente com um valor (completedStage) ou concluídas excepcionalmente (failedStage) com a exceção fornecida.

3.3. MétodofailedFuture

Signature:<U> CompletableFuture<U> failedFuture(Throwable ex)

O método failedFuture adiciona a capacidade de especificar uma instância excepcionalmenteCompleatebleFuture já concluída.

4. Exemplos de casos de uso

Nesta seção, mostraremos alguns exemplos de como usar algumas das novas APIs.

4.1. Demora

Este exemplo mostrará como atrasar a conclusão de umCompletableFuture com um valor específico em um segundo. Isso pode ser alcançado usando o métodocompleteAsync junto com odelayedExecutor.

CompletableFuture future = new CompletableFuture<>();
future.completeAsync(() -> input, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));



4.2. Completo com valor no tempo limite

Outra maneira de obter um resultado atrasado é usar o métodocompleteOnTimeout. Este exemplo define umCompletableFuture que será resolvido com uma determinada entrada se permanecer não resolvido após 1 segundo.

CompletableFuture future = new CompletableFuture<>();
future.completeOnTimeout(input, 1, TimeUnit.SECONDS);



4.3. Tempo esgotado

Outra possibilidade é o tempo limite, que resolve o futuro excepcionalmente comTimeoutException. Por exemplo, tendoCompletableFuture expirando após 1 segundo, não é concluído antes disso.

CompletableFuture future = new CompletableFuture<>();
future.orTimeout(1, TimeUnit.SECONDS);





5. Conclusão

Em conclusão, Java 9 vem com várias adições à APICompletableFuture, agora tem melhor suporte para subclasses, graças ao construtor virtualnewIncompleteFuture, é possível assumir o controle sobre oCompletionStage instâncias retornadas na maioria da APICompletionStage.

Definitivamente, possui melhor suporte para atrasos e tempos limites, como mostrado anteriormente. Os métodos de utilitário adicionados seguem um padrão razoável, dando aCompletableFuture uma maneira conveniente de especificar instâncias resolvidas.

Os exemplos usados ​​neste artigo podem ser encontrados em nossoGitHub repository.