Java 9 CompletableFuture Улучшения API

Усовершенствования API Java 9 CompletableFuture

1. Вступление

В Java 9 внесены некоторые изменения в классCompletableFuture. Такие изменения были введены как частьJEP 266 для рассмотрения распространенных жалоб и предложений с момента его появления в JDK 8, в частности, поддержки задержек и тайм-аутов, лучшей поддержки подклассов и нескольких служебных методов.

В отношении кода API поставляется с восемью новыми методами и пятью новыми статическими методами. Чтобы включить такие добавления, было изменено примерно 1500 из 2400 строк кода (согласно Open JDK).

2. Дополнения к Instance API

Как уже упоминалось, API экземпляра поставляется с восемью новыми дополнениями:

  1. Исполнитель defaultExecutor ()

  2. CompletableFuture newIncompleteFuture ()

  3. CompletableFuture копия ()

  4. CompletionStage minimalCompletionStage ()

  5. CompletableFuture completeAsync (Поставщик поставщик, исполнитель исполнитель)

  6. CompletableFuture completeAsync (Поставщик поставщика)

  7. CompletableFuture orTimeout (длинный таймаут, единица TimeUnit)

  8. CompletableFuture completeOnTimeout (значение T, длительный тайм-аут, единица TimeUnit)

2.1. МетодdefaultExecutor()

Signature:Executor defaultExecutor()

Возвращает значение по умолчаниюExecutor, используемое для асинхронных методов, которые не указываютExecutor.

new CompletableFuture().defaultExecutor()

Это может быть переопределено подклассами, возвращающими исполнителя, предоставляющего, по крайней мере, один независимый поток.

2.2. МетодnewIncompleteFuture()

Signature:CompletableFuture<U> newIncompleteFuture()

newIncompleteFuture, также известный как «виртуальный конструктор», используется для получения нового завершаемого будущего экземпляра того же типа.

new CompletableFuture().newIncompleteFuture()

Этот метод особенно полезен при создании подклассаCompletableFuture, главным образом потому, что он используется внутри почти всех методов, возвращающих новыйCompletionStage, позволяя подклассам контролировать, какой подтип возвращается такими методами.

2.3. Методcopy()

Signature:CompletableFuture<T> copy()

Этот метод возвращает новыйCompletableFuture, который:

  • Когда это завершается нормально, новый также завершается нормально

  • Когда это завершается исключительно за исключением X, новый также завершается исключительно сCompletionException с X в качестве причины

new CompletableFuture().copy()

Этот метод может быть полезен в качестве формы «защитного копирования», чтобы предотвратить выполнение клиентами, при этом сохраняя возможность упорядочивать зависимые действия для определенного экземпляраCompletableFuture.

2.4. МетодminimalCompletionStage()

Signature:CompletionStage<T> minimalCompletionStage()

Этот метод возвращает новыйCompletionStage, который ведет себя точно так же, как описано в методе копирования, однако такой новый экземпляр выдаетUnsupportedOperationException при каждой попытке получить или установить разрешенное значение.

new CompletableFuture().minimalCompletionStage()

НовыйCompletableFuture со всеми доступными методами может быть получен с помощью методаtoCompletableFuture, доступного в APICompletionStage.

2.5. МетодыcompleteAsync()

Для асинхронного завершенияCompletableFuture следует использовать методcompleteAsync, используя значение, заданное предоставленнымSupplier.

Signatures:

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

Разница между этими двумя перегруженными методами заключается в существовании второго аргумента, в котором можно указатьExecutor, выполняющие задачу. Если ничего не указано, будет использоваться исполнитель по умолчанию (возвращенный методомdefaultExecutor).

2.6. МетодыorTimeout()

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

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

РазрешаетCompletableFuture исключительно с помощьюTimeoutException, если он не завершен до указанного тайм-аута.

2.7. МетодcompleteOnTimeout()

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

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

Обычно завершаетCompletableFuture с указанным значением, если только он не завершается до указанного времени ожидания.

3. Статические дополнения API

Также были добавлены некоторые служебные методы. Они есть:

  1. Executor delayedExecutor (длинная задержка, блок TimeUnit, исполнитель-исполнитель)

  2. Executor delayedExecutor (длинная задержка, единица TimeUnit)

  3. CompletionStage completedStage (значение U)

  4. CompletionStage failedStage (Throwable ex)

  5. CompletableFuture failedFuture (Throwable ex)

3.1. МетодыdelayedExecutor

Signatures:

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

Возвращает новыйExecutor, который отправляет задачу заданному базовому исполнителю после заданной задержки (или без задержки, если не положительный результат). Каждая задержка начинается после вызова метода execute возвращенного исполнителя. Если исполнитель не указан, будет использоваться исполнитель по умолчанию (ForkJoinPool.commonPool()).

3.2. МетодыcompletedStage иfailedStage

Signatures:

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

Эти служебные методы возвращают уже разрешенные экземплярыCompletionStage, либо завершенные нормально со значением (completedStage), либо завершенные в исключительных случаях (failedStage) с данным исключением.

3.3. МетодfailedFuture

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

Метод failedFuture добавляет возможность указать уже завершенный исключительноCompleatebleFuture экземпляр.

4. Примеры использования

В этом разделе вы увидите несколько примеров того, как использовать некоторые из новых API.

4.1. задержка

Этот пример покажет, как отложить завершениеCompletableFuture с определенным значением на одну секунду. Этого можно добиться, используя методcompleteAsync вместе сdelayedExecutor.

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



4.2. Завершить со значением по истечении времени ожидания

Другой способ получить отсроченный результат - использовать методcompleteOnTimeout. В этом примере определяетсяCompletableFuture, который будет разрешен с заданным входом, если он останется неразрешенным через 1 секунду.

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



4.3. Тайм-аут

Другая возможность - тайм-аут, который решает будущее исключительно сTimeoutException. Например, таймаутCompletableFuture истекает через 1 секунду при условии, что он не завершен до этого.

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





5. Заключение

В заключение, Java 9 поставляется с несколькими дополнениями к APICompletableFuture, теперь он имеет лучшую поддержку подклассов, благодаря виртуальному конструкторуnewIncompleteFuture, можно взять под контрольCompletionStage экземпляры, возвращаемые в большинстве APICompletionStage.

Это, безусловно, лучше поддерживает задержки и тайм-ауты, как показано ранее. Добавленные служебные методы следуют разумному шаблону, предоставляяCompletableFuture удобный способ указать разрешенные экземпляры.

Примеры, использованные в этой статье, можно найти в нашемGitHub repository.