Java 9 CompletableFuture API подобрения

1. Въведение

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

Кодово, API се предлага с осем нови метода и пет нови статични метода. За да се активират такива допълнения, бяха променени приблизително 1500 от 2400 реда код (според Open JDK).

2. Добавки на API за инстанция

Както споменахме, API на екземпляра се предлага с осем нови допълнения, те са:

  1. Изпълнител по подразбиране Изпълнител ()
  2. CompletableFuture newIncompleteFuture ()
  3. Завършващо бъдещо копие ()
  4. CompletionStage minimalCompletionStage ()
  5. CompletableFuture completeAsync (доставчик на доставчик, изпълнител на изпълнител)
  6. CompletableFuture completeAsync (доставчик на доставчик)
  7. CompletableFuture orTimeout (дълго време за изчакване, единица TimeUnit)
  8. CompletableFuture completeOnTimeout (T стойност, дълъг таймаут, TimeUnit единица)

2.1. Метод по подразбиране Изпълнител ()

Подпис : Изпълнител по подразбиране Изпълнител ()

Връща изпълнителя по подразбиране, използван за асинхронни методи, които не посочват изпълнител .

new CompletableFuture().defaultExecutor()

Това може да бъде заменено от подкласове, връщащи изпълнител, предоставящ поне една независима нишка.

2.2. Метод newIncompleteFuture ()

Подпис : CompletableFuture newIncompleteFuture ()

В newIncompleteFuture , известен също като "виртуален конструктор", се използва за получаване на нов completable бъдеще инстанция от същия тип.

new CompletableFuture().newIncompleteFuture()

Този метод е особено полезен при подкласиране на CompletableFuture , главно защото се използва вътрешно в почти всички методи, връщащи нов CompletionStage , позволявайки на подкласовете да контролират какъв подтип се връща от такива методи.

2.3. Копиране на метод ()

Подпис : Изпълним Бъдещо копие ()

Този метод връща нов CompletableFuture, който:

  • Когато това завърши нормално, новото също се завършва нормално
  • Когато това се изпълни изключително с изключение X, новото също се завършва изключително с CompletionException с X като причина
new CompletableFuture().copy()

Този метод може да бъде полезен като форма на „защитно копиране“, за да се предотврати завършването на клиенти, като същевременно е в състояние да организира зависими действия върху конкретен екземпляр на CompletableFuture .

2.4. Метод minimalCompletionStage ()

Подпис : CompletionStage minimalCompletionStage ()

Този метод връща нов CompletionStage, който се държи по същия начин, както е описано от метода за копиране, но такъв нов екземпляр хвърля UnsupportedOperationException при всеки опит за извличане или задаване на разрешената стойност.

new CompletableFuture().minimalCompletionStage()

Нов CompletableFuture с всички налични методи може да бъде извлечен с помощта на метода toCompletableFuture , наличен в API на CompletionStage .

2.5. Методи completeAsync ()

Методът completeAsync трябва да се използва за завършване на CompletableFuture асинхронно, като се използва стойността, дадена от предоставения доставчик .

Подписи :

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

Разликата между тези два претоварени метода е съществуването на втория аргумент, където Изпълнителят, изпълняващ задачата, може да бъде посочен. Ако не се предостави нищо, ще се използва изпълнител по подразбиране (върнат от метода defaultExecutor ).

2.6. Методи orTimeout ()

Подпис : CompletableFuture orTimeout (дълго време за изчакване, единица TimeUnit)

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

Решава CompletableFuture по изключение с TimeoutException , освен ако не е завършен преди определеното време за изчакване.

2.7. Метод completeOnTimeout ()

Подпис : CompletableFuture completeOnTimeout (T стойност, дълъг таймаут, UnitUnit единица)

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

Завършва CompletableFuture обикновено с посочената стойност, освен ако не е завършена преди посочения таймаут.

3. Статични API добавки

Добавени са и някои полезни методи. Те са:

  1. Изпълнител отложен Изпълнител (дълго закъснение, единица TimeUnit, изпълнител на изпълнител)
  2. Изпълнител отложен Изпълнител (дълго закъснение, единица TimeUnit)
  3. CompletionStage completedStage(U value)
  4. CompletionStage failedStage(Throwable ex)
  5. CompletableFuture failedFuture(Throwable ex)

3.1. Methods delayedExecutor

Signatures:

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

Returns a new Executor that submits a task to the given base executor after the given delay (or no delay if non-positive). Each delay commences upon invocation of the returned executor's execute method. If no executor is specified the default executor (ForkJoinPool.commonPool()) will be used.

3.2. Methods completedStage and failedStage

Signatures:

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

This utility methods return already resolved CompletionStage instances, either completed normally with a value (completedStage) or completed exceptionally (failedStage) with the given exception.

3.3. Method failedFuture

Signature: CompletableFuture failedFuture(Throwable ex)

The failedFuture method adds the ability to specify an already completed exceptionally CompleatebleFuture instance.

4. Example Use Cases

Within this section, one will show some examples on how to use some of the new API.

4.1. Delay

This example will show how to delay the completion of a CompletableFuture with a specific value by one second. That can be achieved by using the completeAsync method together with the delayedExecutor.

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

4.2. Complete With Value on Timeout

Another way to achieve a delayed result is to use the completeOnTimeout method. This example defines a CompletableFuture that will be resolved with a given input if it stays unresolved after 1 second.

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

4.3. Timeout

Another possibility is timing out which resolves the future exceptionally with TimeoutException. For example, having the CompletableFuture timing out after 1 second given it is not completed before that.

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

5. Conclusion

В заключение, Java 9 се предлага с няколко допълнения към API на CompletableFuture , вече има по-добра поддръжка за подкласиране, благодарение на виртуалния конструктор newIncompleteFuture е възможно да се поеме контрол над екземплярите CompletionStage, върнати в повечето API на CompletionStage .

Определено има по-добра поддръжка за закъснения и изчаквания, както беше показано по-рано. Добавените методи на полезност следват разумен модел, давайки на CompletableFuture удобен начин за посочване на разрешени екземпляри.

Примерите, използвани в тази статия, могат да бъдат намерени в нашето хранилище на GitHub.