Rozdiel medzi vláknom a virtuálnym vláknom v Jave

1. Úvod

V tomto tutoriáli si ukážeme rozdiel medzi tradičnými vláknami v Jave a virtuálnymi vláknami zavedenými v Project Loom.

Ďalej budeme zdieľať niekoľko prípadov použitia pre virtuálne vlákna a API, ktoré projekt zaviedol.

Predtým, ako začneme, si musíme uvedomiť tento projekt sa aktívne vyvíja. Spustíme naše príklady na loom VM s prednostným prístupom: openjdk-15-loom + 4-55_windows-x64_bin.

Novšie verzie zostavení môžu meniť a rozbíjať súčasné API. To znamená, že už došlo k významnej zmene v API, ako sa predtým používalo java.lang.Vlákno trieda bola odstránená a nahradená novou java.lang.VirtualThread trieda.

2. Prehľad na vysokej úrovni pre vlákno vs. virtuálne vlákno

Na vysokej úrovni vlákno je spravované a plánované operačným systémom, zatiaľ čo virtuálne vlákno je spravované a plánované virtuálnym strojom. Teraz, aby sme vytvorili nové vlákno jadra, musíme urobiť systémové volanie, a to je nákladná operácia.

Preto namiesto prerozdelenia a prerozdelenia vlákien podľa potreby používame skupiny vlákien. Ďalej, ak by sme chceli rozšíriť našu aplikáciu pridaním ďalších vlákien, vzhľadom na prepínanie kontextu a ich pamäťovú stopu, môžu byť náklady na údržbu týchto vlákien značné a ovplyvniť čas spracovania.

Potom zvyčajne tieto vlákna nechceme blokovať, čo má za následok použitie neblokujúcich I / O API a asynchrónnych API, ktoré môžu náš kód preplniť.

Naopak, virtuálne vlákna sú spravované JVM. Preto ich pridelenie nevyžaduje systémové volanie, a sú bez kontextu kontextu operačného systému. Virtuálne vlákna navyše fungujú na nosnom vlákne, ktoré je skutočným vláknom jadra používaným pod kapotou. Výsledkom je, že sme oslobodení od kontextového prepínania systému, a tak by sa nám mohlo vytvoriť oveľa viac takýchto virtuálnych vlákien.

Ďalej je kľúčovou vlastnosťou virtuálnych vlákien to, že neblokujú naše nosné vlákno. S tým sa blokovanie virtuálneho vlákna stáva oveľa lacnejšou operáciou, pretože JVM naplánuje ďalšie virtuálne vlákno, pričom nosné vlákno zostane odblokované.

Nakoniec by sme nemuseli siahať po NIO alebo Async API. Výsledkom by mal byť čitateľnejší kód, ktorý je ľahšie pochopiteľný a laditeľný. Napriek tomu pokračovanie môže potenciálne zablokovať nosný závit - konkrétne, keď vlákno volá natívnu metódu a odtiaľ vykonáva blokujúce operácie.

3. Nové API na vytváranie vlákien

V Loom sme dostali nové API staviteľa do Závit triedy spolu s niekoľkými továrenskými metódami. Pozrime sa, ako môžeme vytvoriť štandardné a virtuálne továrne a využiť ich na vykonávanie vlákien:

Spustiteľný printThread = () -> System.out.println (Thread.currentThread ()); ThreadFactory virtualThreadFactory = Thread.builder (). Virtual (). Factory (); ThreadFactory kernelThreadFactory = Thread.builder (). Factory (); Vlákno virtualThread = virtualThreadFactory.newThread (printThread); Vlákno kernelThread = kernelThreadFactory.newThread (printThread); virtualThread.start (); kernelThread.start ();

Tu je výstup z vyššie uvedeného behu:

Vlákno [Vlákno-0,5, hlavné] VirtualThread [, ForkJoinPool-1-worker-3, CarrierThreads]

Tu je prvý záznam štandardom natiahnuť výstup vlákna jadra.

Teraz vidíme na výstupe, že virtuálne vlákno nemá žiadny názov a vykonáva sa na pracovnom vlákne fondu Fork-Join z CarrierThreads skupina vlákien.

Ako vidíme, bez ohľadu na základnú implementáciu, API je rovnaké a to znamená, že by sme mohli ľahko spustiť existujúci kód na virtuálnych vláknach.

Aby sme ich mohli využívať, nemusíme sa učiť nové API.

4. Zloženie virtuálneho vlákna

Je to pokračovanie a plánovač že spolu tvoria virtuálne vlákno. Teraz môže byť naším plánovačom užívateľského režimu akákoľvek implementácia Exekútor rozhranie. Vyššie uvedený príklad nám ukázal, že štandardne fungujeme na ForkJoinPool.

Teraz, podobne ako vlákno jadra - ktoré je možné spustiť na CPU, potom zaparkovať, naplánovať naspäť a potom pokračovať v jeho vykonávaní - pokračovanie je vykonávacia jednotka, ktorú je možné spustiť, potom zaparkovať (získať), naplánovať naspäť a pokračovať jeho vykonávanie rovnakým spôsobom od miesta, kde skončilo, a namiesto toho, aby sa spoliehalo na operačný systém, bude stále spravované JVM.

Upozorňujeme, že pokračovaním je rozhranie API na nízkej úrovni a že programátori by na spustenie virtuálnych vlákien mali používať rozhrania API vyššej úrovne, ako je rozhranie API staviteľa.

Aby sme však ukázali, ako to funguje pod kapotou, spustíme naše experimentálne pokračovanie:

var rozsah = nový ContinuationScope ("C1"); var c = new Continuation (scope, () -> {System.out.println ("Start C1"); Continuation.yield (scope); System.out.println ("End C1");}); while (! c.isDone ()) {System.out.println ("Spustiť beh ()"); c.run (); System.out.println ("Ukončiť beh ()"); }

Tu je výstup z vyššie uvedeného behu:

Začiatok chodu () Začiatok C1 Koniec chodu () Začiatok chodu () Koniec C1 Koniec chodu ()

V tomto príklade sme pokračovali a v určitom okamihu sme sa rozhodli zastaviť spracovanie. Potom, keď sme to znovu spustili, pokračovalo naše pokračovanie od miesta, kde to skončilo. Na výstupe vidíme, že run () metóda bola volaná dvakrát, ale pokračovanie bolo spustené raz a potom pokračovalo v vykonávaní pri druhom behu, odkiaľ skončilo.

Takto má JVM spracovávať blokovacie operácie. Akonáhle dôjde k blokujúcej operácii, pokračovanie sa uvoľní, pričom nosný závit zostane odblokovaný.

Takže sa stalo to, že naše hlavné vlákno vytvorilo vo svojom zásobníku volaní nový rámec zásobníka pre run () metódou a pristúpila k exekúcii. Potom, ako sa pokračovanie vzdalo, JVM uložil súčasný stav jeho vykonávania.

Ďalej hlavné vlákno pokračovalo vo vykonávaní, akoby run () metóda sa vrátila a pokračovala s zatiaľ čo slučka. Po druhej výzve na pokračovanie bežať metódou JVM obnovil stav hlavného vlákna do bodu, kde pokračovanie prinieslo a dokončil vykonávanie.

5. Záver

V tomto článku sme diskutovali o rozdieloch medzi vláknom jadra a virtuálnym vláknom. Ďalej sme si ukázali, ako môžeme na spustenie virtuálnych vlákien použiť nové API na vytváranie vlákien z Project Loom.

Nakoniec sme si ukázali, čo je to pokračovanie a ako to funguje pod kapotou. Stav Project Loom môžeme ďalej preskúmať kontrolou virtuálneho počítača s prednostným prístupom. Prípadne môžeme preskúmať viac už štandardizovaných rozhraní API súbežnosti Java.


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