A CompltableFuture sa používa na asynchrónne programovanie. Asynchrónne programovanie znamená písanie neblokovacieho kódu. Spustí úlohu na samostatnom vlákne ako hlavné vlákno aplikácie a informuje hlavné vlákno o jej priebehu, dokončení alebo zlyhaní.
Týmto spôsobom hlavné vlákno neblokuje a nečaká na dokončenie úlohy. Ostatné úlohy sa vykonávajú paralelne. Paralelnosť zlepšuje výkon programu.
CompletableFuture je trieda v jazyku Java. Patrí do balíka java.util.cocurrent. Implementuje rozhranie CompletionStage a Future.
Fáza dokončenia
- Vykoná akciu a po dokončení ďalšej fázy dokončenia vráti hodnotu.
- Model úlohy, ktorý môže spustiť iné úlohy.
Ide teda o prvok reťazca.
Keď sa viac ako jedno vlákno pokúsi dokončiť – výnimočne dokončiť alebo zrušiť CompletableFuture, uspeje iba jedno z nich.
rozvetvené stromy
Budúcnosť vs. CompletableFuture
CompletableFuture je rozšírenie rozhrania Java Future API, ktoré bolo predstavené v jazyku Java 8.
Future sa používa na asynchrónne programovanie. Poskytuje dve metódy, isDone() a get(). Metódy získajú výsledok výpočtu po jeho dokončení.
Obmedzenia budúcnosti
- Budúcnosť nemôže byť vzájomne úplná.
- Bez blokovania nemôžeme vykonať ďalšiu akciu s výsledkom Future.
- Budúcnosť nemá žiadnu výnimku.
- Nemôžeme spájať viaceré budúcnosti.
Budúcnosť má toľko obmedzení, preto máme CompletableFuture. CompletableFuture poskytuje širokú škálu metód na vytváranie viacerých futures, reťazenie a kombinovanie. Má tiež komplexnú podporu spracovania výnimiek.
Vytvorenie CompletableFuture
CompletableFuture môžeme vytvoriť iba pomocou nasledujúceho konštruktora bez argumentov.
CompletableFuture CompletableFuture = new CompletableFuture();
Príklad
Najčastejšie používané metódy CompletableFuture sú:
js viacriadkový reťazec
import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; public class CompletableFutureExample1 { public static void main(String[] args) { try { List list = Arrays.asList(5,9,14); list.stream().map(num->CompletableFuture.supplyAsync(()->getNumber(num))).map(CompletableFuture->CompletableFuture.thenApply(n- >n*n)).map(t->t.join()).forEach(s->System.out.println(s)); } catch (Exception e) { e.printStackTrace(); } } private static int getNumber(int a) { return a*a; } }
Výkon:
Spracovanie výnimiek z CompletableFuture
Zvážte nasledujúci obrázok, ktorý predstavuje päť CF:
Predpokladajme, že päť CF v prevádzke a CF21 vyvolá výnimku, potom sú všetky závislé CF (CF31 a CF41) chybné. Znamená to, že:
- Volanie metódy isCompletedExceptionally() vráti hodnotu true.
- Volanie get() vyvolá ExecutionException, ktorá spôsobí koreňovú výnimku.
Zoberme si nasledujúci obrázok, na ktorom sme vytvorili CF30 s výnimkou.
Keď sa CF21 spustí normálne, potom CF30 iba odošle hodnotu. Ak vyvolá výnimku, CF30 ju spracuje a vygeneruje hodnotu pre CF31.
Existujú tri spôsoby spracovania výnimky:
public CompletableFuture exceptionally(Function function); public CompletableFuture hadle(BiFunction bifunction); public CompletableFuture whenComplete(BiConsumer action);