Asynchrónne programovanie v Jave

1. Prehľad

S rastúcim dopytom po písaní neblokujúceho kódu potrebujeme spôsoby, ako tento kód asynchrónne spustiť.

V tomto výučbe sa pozrieme na niekoľko spôsobov, ako dosiahnuť asynchrónne programovanie v Jave. Preskúmame tiež niekoľko knižníc Java, ktoré poskytujú hotové riešenia.

2. Asynchrónne programovanie v Jave

2.1. Závit

Môžeme vytvoriť nové vlákno na vykonávanie akejkoľvek operácie asynchrónne. S vydaním výrazov lambda v prostredí Java 8 je prehľadnejšie a čitateľnejšie.

Vytvorme nové vlákno, ktoré počíta a tlačí faktoriál čísla:

int cislo = 20; Vlákno newThread = new Thread (() -> {System.out.println ("Factorial of" + number + "is:" + factororial (number));}); newThread.start ();

2.2. FutureTask

Od verzie Java 5 sa Budúcnosť Rozhranie poskytuje spôsob vykonávania asynchrónnych operácií pomocou FutureTask.

Môžeme použiť Predložiť metóda ExecutorService vykonať úlohu asynchrónne a vrátiť inštanciu súboru FutureTask.

Poďme teda nájsť faktoriál čísla:

ExecutorService threadpool = Executors.newCachedThreadPool (); Future futureTask = threadpool.submit (() -> faktoriál (číslo)); while (! futureTask.isDone ()) {System.out.println ("FutureTask ešte nie je dokončený ..."); } long result = futureTask.get (); threadpool.shutdown ();

Tu sme použili je hotové metóda poskytovaná Budúcnosť dokončiť úlohu. Po dokončení môžeme výsledok načítať pomocou dostať metóda.

2.3. CompletableFuture

Bola predstavená Java 8 CompletableFuture s kombináciou a Budúcnosť a DokončenieStage. Poskytuje rôzne metódy ako supplyAsync, runAsynca thenApplyAsync pre asynchrónne programovanie.

Takže poďme použiť CompletableFuture namiesto FutureTask nájsť faktoriál čísla:

CompletableFuture completableFuture = CompletableFuture.supplyAsync (() -> faktoriál (číslo)); while (! completableFuture.isDone ()) {System.out.println ("CompletableFuture ešte nie je dokončený ..."); } long result = completableFuture.get ();

Nepotrebujeme používať ExecutorService výslovne. The CompletableFuture interne používa ForkJoinPool asynchrónne zvládnuť úlohu. Vďaka tomu je náš kód oveľa čistejší.

3. Guava

Guava poskytuje ListenableFuture triedy na vykonávanie asynchrónnych operácií.

Najskôr pridáme najnovšie guava Závislosť Maven:

 com.google.guava guava 28.2-jre 

Potom nájdeme faktoriál čísla pomocou funkcie ListenableFuture:

ExecutorService threadpool = Executors.newCachedThreadPool (); Služba ListeningExecutorService = MoreExecutors.listeningDecorator (threadpool); ListenableFuture guavaFuture = (ListenableFuture) service.submit (() -> faktoriál (číslo)); long result = guavaFuture.get ();

Tu je Viac Exekútorov trieda poskytuje inštanciu súboru ListeningExecutorService trieda. Potom ListeningExecutorService.submit metóda vykonáva úlohu asynchrónne a vracia inštanciu súboru ListenableFuture.

Guava má tiež Budúcnosť trieda, ktorá poskytuje metódy ako submitAsync, harmonogramAsynca transformAsync pripútať ListenableFutures podobne ako CompletableFuture.

Pozrime sa napríklad, ako sa používa Futures.submitAsync namiesto ListeningExecutorService.submit metóda:

Služba ListeningExecutorService = MoreExecutors.listeningDecorator (threadpool); AsyncCallable asyncCallable = Callables.asAsyncCallable (new Callable () {public Long call () {return factororial (number);}}, service); ListenableFuture guavaFuture = Futures.submitAsync (asyncCallable, služba);

Tu je submitAsync metóda vyžaduje argument o AsyncCallable, ktorý je vytvorený pomocou Zavolajuce trieda.

Okrem toho Budúcnosť trieda poskytuje addCallback metóda registrácie úspešných a zlyhaných spätných volaní:

Futures.addCallback (factorialFuture, new FutureCallback () {public void onSuccess (Long factororial) {System.out.println (factorial);} public void onFailure (Throwable thrown) {thrown.getCause ();}}, service);

4. EA Async

Spoločnosť Electronic Arts priniesla funkciu asynchronného čakania z .NET do ekosystému Java prostredníctvom platformy ea-async knižnica.

Knižnica umožňuje postupné písanie asynchrónneho (neblokujúceho) kódu. Preto uľahčuje asynchrónne programovanie a mierku prirodzene zvyšuje.

Najskôr pridáme najnovšie ea-async Maven závislosť na pom.xml:

 com.ea.async ea-async 1.2.3 

Potom transformujme predtým diskutované CompletableFuture kód pomocou čakať metóda poskytovaná EA Async trieda:

static {Async.init (); } public long factorialUsingEAAsync (int number) {CompletableFuture completableFuture = CompletableFuture.supplyAsync (() -> faktoriál (číslo)); long result = Async.await (completableFuture); }

Tu zavoláme do Async.init metóda v statický blok na inicializáciu Async runtime prístrojové vybavenie.

Async prístrojové vybavenie transformuje kód za behu a prepíše hovor na čakať metódou, správať sa podobne ako pri použití reťazca CompletableFuture.

Preto hovor na čakať metóda je podobná volaniu Future.join.

Môžeme použiť - javaagent Parameter JVM pre prístrojové vybavenie v čase kompilácie. Toto je alternatíva k Async.init metóda:

java -javaagent: ea-async-1.2.3.jar -cp 

Pozrime sa na ďalší príklad postupného zápisu asynchrónneho kódu.

Najskôr vykonáme niekoľko reťazových operácií asynchrónne pomocou metód skladania ako thenComposeAsync a thenAcceptAsync z CompletableFuture trieda:

CompletableFuture completableFuture = ahoj (). PotomComposeAsync (ahoj -> mergeWorld (ahoj)). Potom AcceptAsync (helloWorld -> tlač (helloWorld)). Výnimočne (hodiť -> {System.out.println (throwable.getCause ()); vrátiť null ;}); completableFuture.get ();

Potom môžeme kód transformovať pomocou EA Async.await ():

skúsiť {String hello = await (hello ()); Reťazec helloWorld = await (mergeWorld (hello)); await (CompletableFuture.runAsync (() -> tlač (helloWorld))); } catch (Výnimka e) {e.printStackTrace (); }

Implementácia sa podobá sekvenčnému blokovaciemu kódu. Avšak čakať metóda neblokuje kód.

Ako už bolo uvedené, všetky výzvy na čakať metóda bude prepísaná Async prístrojové vybavenie pracovať podobne ako Future.join metóda.

Takže raz asynchrónne vykonávanie Ahoj metóda je hotová, Budúcnosť výsledok sa odovzdá mergeWorld metóda. Potom je výsledok odovzdaný do poslednej exekúcie pomocou CompletableFuture.runAsync metóda.

5. Kaktusy

Cactoos je knižnica Java založená na objektovo orientovaných princípoch.

Je to alternatíva k programom Google Guava a Apache Commons, ktorá poskytuje bežné objekty na vykonávanie rôznych operácií.

Najskôr pridajme najnovšie kaktusy Závislosť Maven:

 org.kaktusy kaktusy 0,43 

Knižnica poskytuje Async trieda pre asynchrónne operácie.

Takže môžeme nájsť faktoriál čísla pomocou inštancie Cactoos Async trieda:

Async asyncFunction = new Async (vstup -> faktoriál (vstup)); Budúca asyncFuture = asyncFunction.apply (číslo); long result = asyncFuture.get ();

Tu, the uplatniť metóda vykonáva operáciu pomocou ExecutorService.submit metóda a vráti inštanciu súboru Budúcnosť rozhranie.

Podobne Async trieda má vykon metóda, ktorá poskytuje rovnakú funkciu bez návratovej hodnoty.

Poznámka: Knižnica Cactoos je v počiatočných fázach vývoja a ešte nemusí byť vhodná na produkčné použitie.

6. Aspekty Jcabi

Spoločnosť Jcabi-Aspects poskytuje @Async anotácia pre asynchrónne programovanie prostredníctvom aspektov AspectJ AOP.

Najskôr pridajme najnovšie aspekty jcabi Závislosť Maven:

 com.jcabi jcabi-aspekty 0.22.6 

The aspekty jcabi Knižnica vyžaduje podporu runtime AspectJ. Takže pridáme aspectjrt Závislosť Maven:

 org.aspectj aspectjrt 1.9.5 

Ďalej pridáme jcabi-maven-plugin doplnok, ktorý splieta binárne súbory s aspektmi AspectJ. Doplnok poskytuje ajc cieľ, ktorý za nás odvádza všetku prácu:

 com.jcabi jcabi-maven-plugin 0.14.1 ajc org.aspectj aspectjtools 1.9.1 org.aspectj aspectjweaver 1.9.1 

Takže sme všetci pripravení používať aspekty AOP na asynchrónne programovanie:

@Async @Loggable public Future factorialUsingAspect (int číslo) {Future factorialFuture = CompletableFuture.completedFuture (faktoriál (číslo)); návratový faktoriál Budúcnosť; }

Keď zostavujeme kód, knižnica vloží radu AOP namiesto @Async anotácia prostredníctvom tkania AspectJpre asynchrónne vykonávanie faktororialUsingAspect metóda.

Poďme teda zostaviť triedu pomocou príkazu Maven:

inštalácia mvn

Výstup z jcabi-maven-plugin môže vyzerať ako:

 --- jcabi-maven-plugin: 0.14.1: ajc (predvolené) @ java-async --- [INFO] jcabi-aspekty 0.18 / 55a5c13 spustil nové vlákno démona jcabi-logable na sledovanie metód komentovaných @Loggable [INFO] Netkané triedy sa skopírujú do / tutorials / java-async / target / unwoven [INFO] jcabi-aspekty 0.18 / 55a5c13 spustilo nové vlákno démona jcabi-cacheable pre automatické čistenie vypršaných hodnôt @Cacheable [INFO] výsledok ajc: 10 súborov ) spracované, 0 bodových tkaní, 0 chýb, 0 varovaní

To, či je naša trieda utkaná správne, môžeme overiť kontrolou denníkov v jcabi-ajc.log súbor vygenerovaný doplnkom Maven:

Pripojte bod „method-execution (java.util.concurrent.Future com.baeldung.async.JavaAsync.factorialUsingJcabiAspect (int))“ do typu „com.baeldung.async.JavaAsync“ (JavaAsync.java:158), ktorý odporúča rada z 'com.jcabi.aspects.aj.MethodAsyncRunner' (jcabi-aspekty-0.22.6.jar! MethodAsyncRunner.class (z MethodAsyncRunner.java))

Potom triedu spustíme ako jednoduchú aplikáciu Java a výstup bude vyzerať takto:

17: 46: 58.245 [main] INFO com.jcabi.aspects.aj.NamedThreads - jcabi-aspekty 0.22.6 / 3f0a1f7 spustili nové vlákno démona jcabi-logable na sledovanie anotovaných metód @Loggable 17:46: 58.355 [hlavné] INFO com.jcabi.aspects.aj.NamedThreads - jcabi-aspekty 0.22.6 / 3f0a1f7 spustili nové démonové vlákno jcabi-async na vykonávanie asynchrónnej metódy 17:46: 58,358 [jcabi-async] INFO com.baeldung.async.JavaAsync - #factorialUsingJcabiAspect (20): „[chránený e-mailom] [dokončené normálne]“ za 44,64 µs

Takže môžeme vidieť nové vlákno démona jcabi-async je vytvorená knižnicou, ktorá vykonala úlohu asynchrónne.

Podobne logovanie umožňuje server @ Prihlásiteľné anotácia poskytnutá knižnicou.

7. Záver

V tomto článku sme videli niekoľko spôsobov asynchrónneho programovania v prostredí Java.

Najskôr sme preskúmali vstavané funkcie Java, napríklad FutureTask a CompletableFuture pre asynchrónne programovanie. Potom sme videli niekoľko knižníc ako EA Async a Cactoos s out-of-the-box riešeniami.

Tiež sme preskúmali podporu asynchrónneho vykonávania úloh pomocou Guavy ListenableFuture a Budúcnosť triedy. Na záver sme preskúmali knižnicu jcabi-AspectJ, ktorá prostredníctvom nej poskytuje funkcie AOP @Async anotácia pre volania asynchrónnej metódy.

Ako obvykle sú všetky implementácie kódu dostupné na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found