Testovanie viacvláknového kódu v Jave

1. Úvod

V tomto výučbe sa budeme venovať niektorým základom testovania súbežného programu. Primárne sa zameriame na vláknovú súbežnosť a problémy, ktoré predstavuje pri testovaní.

Pochopíme tiež, ako môžeme vyriešiť niektoré z týchto problémov a efektívne testovať viacvláknový kód v Jave.

2. Súbežné programovanie

Súbežné programovanie sa vzťahuje na programovanie, kde sme rozdeliť veľkú časť výpočtu na menšie, relatívne nezávislé výpočty.

Účelom tohto cvičenia je spustiť tieto menšie výpočty súčasne, prípadne aj paralelne. Aj keď existuje niekoľko spôsobov, ako to dosiahnuť, cieľom je vždy spustiť program rýchlejšie.

2.1. Vlákna a súbežné programovanie

Vďaka tomu, že procesory obsahujú viac jadier ako kedykoľvek predtým, je v popredí súbežné programovanie, ktoré ich efektívne využije. Faktom však zostáva, že súbežné programy je oveľa ťažšie navrhnúť, napísať, otestovať a udržiavať. Takže ak dokážeme napísať efektívne a automatizované testovacie prípady pre súbežné programy, môžeme vyriešiť veľkú časť týchto problémov.

Čo teda sťažuje písanie testov na súbežný kód? Aby sme to pochopili, musíme pochopiť, ako dosiahneme súbežnosť v našich programoch. Jedna z najpopulárnejších techník súbežného programovania zahŕňa použitie vlákien.

Vlákna teraz môžu byť natívne, v takom prípade sú naplánované príslušnými operačnými systémami. Môžeme tiež použiť tzv. Zelené vlákna, ktoré sú naplánované priamo za behu.

2.2. Problémy s testovaním súbežných programov

Bez ohľadu na to, aký typ vlákien používame, ich používanie je sťažené, je komunikácia vlákien. Ak sa nám skutočne podarí napísať program, ktorý obsahuje vlákna, ale komunikáciu bez vlákien, nie je nič lepšie! Realistickejšie povedané, vlákna budú zvyčajne musieť komunikovať. Existujú dva spôsoby, ako to dosiahnuť - zdieľaná pamäť a odovzdávanie správ.

Prevažná časť problém spojený so súčasným programovaním nastáva v dôsledku používania natívnych vlákien so zdieľanou pamäťou. Testovanie takýchto programov je ťažké z rovnakých dôvodov. Viaceré vlákna s prístupom k zdieľanej pamäti spravidla vyžadujú vzájomné vylúčenie. Spravidla to dosiahneme pomocou nejakého ochranného mechanizmu pomocou zámkov.

Ale to môže stále viesť k množstvu problémov, ako sú rasové podmienky, živé zámky, zablokovania a hladové vlákno. Tieto problémy sú navyše občasné, pretože plánovanie vlákien v prípade natívnych vlákien je úplne nedeterministické.

Písanie efektívnych testov pre súčasné programy, ktoré dokážu tieto problémy zistiť deterministicky, je teda skutočne výzvou!

2.3. Anatómia vkladania vlákien

Vieme, že natívne vlákna môžu byť operačnými systémami naplánované nepredvídateľne. V prípade týchto vlákna pristupujú a upravujú zdieľané údaje, vedie k zaujímavému vkladaniu vlákien. Aj keď niektoré z týchto vkladaní môžu byť úplne prijateľné, iné môžu nechať konečné údaje v nežiadúcom stave.

Zoberme si príklad. Predpokladajme, že máme globálne počítadlo, ktoré sa zvyšuje každým vláknom. Na konci spracovania by sme chceli, aby bol stav tohto počítadla úplne rovnaký ako počet vykonaných vlákien:

súkromný int pult; public void increment () {counter ++; }

Teraz prírastok primitívneho celého čísla v Jave nie je atómová operácia. Pozostáva z načítania hodnoty, jej zvyšovania a konečného uloženia. Zatiaľ čo viaceré vlákna vykonávajú rovnakú operáciu, môže to viesť k mnohým možným vkladaniam:

Aj keď toto konkrétne vkladanie prináša úplne prijateľné výsledky, čo takto:

To nie je to, čo sme očakávali. Teraz si predstavte stovky vlákien, ktoré prevádzkujú kód, ktorý je oveľa zložitejší. To povedie k nepredstaviteľným spôsobom, ako sa vlákna budú prekladať.

Existuje niekoľko spôsobov, ako písať kód, ktorý zabráni týmto problémom, ale to nie je predmetom tohto tutoriálu. Synchronizácia pomocou zámku je jednou z bežných, má však problémy spojené s rasovými podmienkami.

3. Testovanie kódu s viacerými vláknami

Teraz, keď rozumieme základným výzvam pri testovaní viacvláknového kódu, uvidíme, ako ich prekonať. Vytvoríme jednoduchý prípad použitia a pokúsime sa simulovať čo najviac problémov súvisiacich so súbežnosťou.

Začnime definovaním jednoduchej triedy, ktorá uchováva počet pravdepodobne všetkého:

public class MyCounter {private int count; public void increment () {int temp = count; pocet = teplota + 1; } // Getter for count}

Toto je zdanlivo neškodný kód, ale nie je ťažké pochopiť, že to nie je bezpečné pre vlákna. Ak náhodou s touto triedou napíšeme súbežný program, bude to určite chybné. Účelom tohto testovania je identifikovať tieto chyby.

3.1. Testovanie nesúbežných častí

Ako všeobecné pravidlo vždy je vhodné otestovať kód tak, že ho izolujete od akéhokoľvek súbežného správania. Týmto sa má rozumne zistiť, že v kóde nie je žiadna iná chyba, ktorá nesúvisí so súbežnosťou. Pozrime sa, ako to môžeme urobiť:

@Test public void testCounter () {Počítadlo MyCounter = nový MyCounter (); pre (int i = 0; i <500; i ++) {counter.increment (); } assertEquals (500, counter.getCount ()); }

Aj keď sa tu veľa nedeje, tento test nám dáva istotu, že funguje minimálne pri absencii súbežnosti.

3.2. Prvý pokus o testovanie pomocou súbežnosti

Poďme znova otestovať ten istý kód, tentokrát v súbežnom nastavení. Pokúsime sa získať prístup k rovnakej inštancii tejto triedy s viacerými vláknami a zistiť, ako sa správa:

@Test public void testCounterWithConcurrency () hodí InterruptedException {int numberOfThreads = 10; Služba ExecutorService = Executors.newFixedThreadPool (10); Západka CountDownLatch = nová CountDownLatch (numberOfThreads); Počítadlo MyCounter = nový MyCounter (); for (int i = 0; i {counter.increment (); latch.countDown ();}); } latch.await (); assertEquals (numberOfThreads, counter.getCount ()); }

Tento test je primeraný, pretože sa snažíme pracovať na zdieľaných dátach s niekoľkými vláknami. Keď udržujeme nízky počet vlákien, napríklad 10, všimneme si, že to prechádza takmer stále. Je zaujímavé, že ak začneme zvyšovať počet vlákien, povedzme na 100, uvidíme, že test začne väčšinou zlyhávať.

3.3. Lepší pokus o testovanie pomocou súbežnosti

Aj keď predchádzajúci test odhalil, že náš kód nie je bezpečný pre vlákna, s týmto strukom je problém. Tento test nie je deterministický, pretože podkladové vlákna sa vkladajú nedeterministickým spôsobom. Naozaj sa nemôžeme spoliehať na tento test nášho programu.

Potrebujeme spôsob, ako riadiť vkladanie vlákien, aby sme mohli odhaliť problémy so súbežnosťou deterministickým spôsobom s oveľa menším počtom vlákien. Začneme vylepšením kódu, ktorý testujeme:

public synchronized void increment () hodí InterruptedException {int temp = count; čakať (100); count = teplota + 1; }

Tu sme vytvorili metódu synchronizované a zaviedlo čakanie medzi dvoma krokmi v rámci metódy. The synchronizované kľúčové slovo zaisťuje, že iba jedno vlákno môže upravovať počítať premennej po druhej a čakanie zavádza oneskorenie medzi každým vykonaním vlákna.

Upozorňujeme, že kód, ktorý plánujeme testovať, nemusíme nevyhnutne upravovať. Pretože však nie je veľa spôsobov, ako môžeme ovplyvniť plánovanie vlákien, uchýlime sa k tomu.

V neskoršej časti uvidíme, ako to môžeme urobiť bez zmeny kódu.

Teraz otestujme tento kód podobne ako predtým:

@ Test public void testSummationWithConcurrency () vyvolá InterruptedException {int numberOfThreads = 2; Služba ExecutorService = Executors.newFixedThreadPool (10); Západka CountDownLatch = nová CountDownLatch (numberOfThreads); Počítadlo MyCounter = nový MyCounter (); for (int i = 0; i {try {counter.increment ();} catch (InterruptedException e) {// Handle exception} latch.countDown ();}); } latch.await (); assertEquals (numberOfThreads, counter.getCount ()); }

Tu to prevádzkujeme iba s dvoma vláknami a je pravdepodobné, že sa nám podarí zistiť chybu, ktorá nám chýbala. To, čo sme tu urobili, je pokúsiť sa dosiahnuť konkrétne vláknové vkladanie, o ktorom vieme, že nás môže ovplyvniť. Aj keď je to dobré na demonštráciu, nemusí sa nám to zdať užitočné z praktických dôvodov.

4. Dostupné testovacie nástroje

S rastom počtu vlákien exponenciálne rastie možný počet spôsobov, ako sa môžu vkladať. Je to jednoducho nie je možné prísť na všetky takéto vkladania a vyskúšať ich. Musíme sa spoliehať na nástroje, ktoré vyvinú pre nás rovnaké alebo podobné úsilie. Našťastie je ich k dispozícii niekoľko, ktoré nám uľahčujú život.

Na testovanie súbežného kódu máme k dispozícii dve široké kategórie nástrojov. Prvý nám umožňuje produkovať primerane vysoký dôraz na súbežný kód s mnohými vláknami. Stres zvyšuje pravdepodobnosť zriedkavého prekladania, a tým zvyšuje naše šance na nájdenie chýb.

Druhá nám umožňuje simulovať konkrétne vkladanie vlákien, čo nám pomáha s väčšou istotou nájsť chyby.

4.1. tempus-fugit

Knižnica Java tempus-fugit pomáha nám ľahko písať a testovať súbežný kód. Tu sa zameriame iba na testovaciu časť tejto knižnice. Už skôr sme videli, že vytváranie stresu na kóde s viacerými vláknami zvyšuje šance na nájdenie chýb súvisiacich so súbežnosťou.

Aj keď môžeme písať pomôcky na výrobu stresu sami, program tempus-fugit poskytuje pohodlné spôsoby, ako to dosiahnuť.

Zopakujme si ten istý kód, pre ktorý sme sa už predtým snažili vytvoriť stres, a pochopme, ako to môžeme dosiahnuť pomocou tempus-fugit:

public class MyCounterTests {@Rule public ConcurrentRule concurrently = new ConcurrentRule (); @Rule public RepeatingRule rule = new RepeatingRule (); súkromné ​​statické počítadlo MyCounter = nový MyCounter (); @ Test @ Concurrent (počet = 10) @ Opakovanie (opakovanie = 10) public void runsMultipleTimes () {counter.increment (); } @AfterClass public static void annotatedTestRunsMultipleTimes () hodí InterruptedException {assertEquals (counter.getCount (), 100); }}

Tu používame dva z nich Pravidlok dispozícii pre nás z tempus-fugit. Tieto pravidlá zachytávajú testy a pomáhajú nám aplikovať požadované správanie, ako je opakovanie a súbežnosť. Účinne teda testovanú operáciu opakujeme desaťkrát z desiatich rôznych vlákien.

Keď zvýšime opakovanie a súbežnosť, zvýši sa naša šanca na detekciu chýb súvisiacich so súbežnosťou.

4.2. Thea Weaver

Thread Weaver je v podstate rámec Java pre testovanie viacvláknového kódu. Už sme videli, že prekladanie vlákien je dosť nepredvídateľné, a preto možno nikdy nenájdeme určité chyby prostredníctvom pravidelných testov. To, čo skutočne potrebujeme, je spôsob kontroly vkladania a testovania všetkých možných vkladaní. To sa v našom predchádzajúcom pokuse ukázalo ako dosť zložitá úloha.

Pozrime sa, ako nám tu Thread Weaver môže pomôcť. Thread Weaver nám umožňuje prekladať vykonávanie dvoch samostatných vlákien mnohými spôsobmi, bez toho aby sme sa museli obávať ako. Dáva nám tiež možnosť mať jemnozrnnú kontrolu nad tým, ako chceme, aby sa vlákna prekladali.

Pozrime sa, ako môžeme vylepšiť náš predchádzajúci naivný pokus:

public class MyCounterTests {private MyCounter counter; @ThreadedBefore public void before () {counter = new MyCounter (); } @ThreadedMain public void mainThread () {counter.increment (); } @ThreadedSecondary public void secondThread () {counter.increment (); } @ThreadedAfter public void after () {assertEquals (2, counter.getCount ()); } @Test public void testCounter () {new AnnotatedTestRunner (). RunTests (this.getClass (), MyCounter.class); }}

Tu sme definovali dve vlákna, ktoré sa snažia zvýšiť náš počítadlo. Thread Weaver sa pokúsi spustiť tento test s týmito vláknami vo všetkých možných scenároch vkladania. Prípadne v jednom z prekladov dostaneme chybu, ktorá je v našom kóde celkom zrejmá.

4.3. ViacvláknovéTC

ViacvláknovéTC je ešte ďalší rámec pre testovanie súbežných aplikácií. Obsahuje metronóm, ktorý sa používa na zabezpečenie jemnej kontroly nad postupnosťou aktivít vo viacerých vláknach. Podporuje testovacie prípady, ktoré vykonávajú konkrétne vkladanie vlákien. V ideálnom prípade by sme teda mali byť schopní testovať každé významné vkladanie v samostatnom vlákne deterministicky.

Kompletný úvod do tejto knižnice bohatej na funkcie teraz presahuje rámec tohto tutoriálu. Určite však vidíme, ako rýchlo nastaviť testy, ktoré nám poskytnú možné vkladanie medzi vykonávaním vlákien.

Pozrime sa, ako môžeme testovať náš kód deterministickejšie s programom MultithreadedTC:

public class MyTests extends MultithreadedTestCase {private MyCounter counter; @Override public void initialize () {counter = new MyCounter (); } public void thread1 () hodí InterruptedException {counter.increment (); } public void thread2 () hodí InterruptedException {counter.increment (); } @Override public void finish () {assertEquals (2, counter.getCount ()); } @Test public void testCounter () hodí Throwable {TestFramework.runManyTimes (new MyTests (), 1000); }}

Tu nastavujeme dve vlákna, aby fungovali na zdieľanom počítadle a zvyšovali ho. Nakonfigurovali sme MultithreadedTC na vykonávanie tohto testu s týmito vláknami až pre tisíc rôznych vkladaní, kým nezistí zlyhanie.

4.4. Java jcstress

OpenJDK udržiava Code Tool Project a poskytuje vývojárske nástroje pre prácu na projektoch OpenJDK. V rámci tohto projektu existuje niekoľko užitočných nástrojov, vrátane stresových testov Java Concurrency Stress Tests (jcstress). Toto sa vyvíja ako experimentálny zväzok a sada testov na preskúmanie správnosti podpory súbežnosti v Jave.

Aj keď sa jedná o experimentálny nástroj, stále ho môžeme využiť na analýzu súbežného kódu a zápis testov na financovanie chýb, ktoré s ním súvisia. Pozrime sa, ako môžeme v tomto tutoriále otestovať kód, ktorý sme doteraz používali. Koncept je z hľadiska použitia dosť podobný:

@JCStressTest @Outcome (id = "1", expect = ACCEPTABLE_INTERESTING, desc = "Jedna aktualizácia sa stratila.") @Outcome (id = "2", expect = ACCEPTABLE, desc = "Obe aktualizácie.") @ Štátna verejná trieda MyCounterTests {súkromné ​​počítadlo MyCounter; @Actor public void actor1 () {counter.increment (); } @Actor public void actor2 () {counter.increment (); } @Arbiter public void arbiter (I_Result r) {r.r1 = counter.getCount (); }}

Tu sme triedu označili anotáciou Štát, čo znamená, že obsahuje údaje zmutované viacerými vláknami. Používame tiež anotáciu Herec, ktorý označuje metódy, ktoré zadržiavajú akcie vykonané rôznymi vláknami.

Na záver tu máme metódu označenú anotáciou Arbiter, ktorý štát v podstate navštívi iba raz Herecnavštívili. Použili sme tiež anotáciu Výsledok definovať naše očakávania.

Celkovo je nastavenie celkom jednoduché a jeho ovládanie je intuitívne. Môžeme to spustiť pomocou testovacieho postroja daného rámcom, ktorý nájde všetky triedy anotované JCStressTest a vykoná ich v niekoľkých iteráciách, aby získal všetky možné vkladania.

5. Ďalšie spôsoby zisťovania problémov so súbežnosťou

Písanie testov pre súbežný kód je ťažké, ale možné. Videli sme výzvy a niektoré populárne spôsoby, ako ich prekonať. Avšak nemusíme byť schopní identifikovať všetky možné problémy so súbežnosťou iba pomocou testov - najmä keď prírastkové náklady na napísanie ďalších testov začnú prevažovať nad ich výhodami.

Preto spolu s primeraným počtom automatizovaných testov môžeme na identifikáciu problémov so súbežnosťou použiť ďalšie techniky. To zvýši naše šance na nájdenie problémov so súbežnosťou bez toho, aby sme sa dostali príliš hlboko do zložitosti automatizovaných testov. Niektorým z nich sa budeme venovať v tejto časti.

5.1. Statická analýza

Statická analýza sa vzťahuje na analýzu programu bez jeho skutočného vykonania. Čo dobrého môže teraz urobiť takáto analýza? K tomu ešte prídeme, ale poďme najskôr pochopiť, ako to kontrastuje s dynamickou analýzou. Testy jednotiek, ktoré sme doteraz napísali, je potrebné spustiť so skutočným vykonaním programu, ktorý testujú. To je dôvod, prečo sú súčasťou toho, čo vo veľkej miere nazývame dynamická analýza.

Upozorňujeme, že statická analýza v žiadnom prípade nenahrádza dynamickú analýzu. Poskytuje však neoceniteľný nástroj na preskúmanie štruktúry kódu a identifikáciu možných chýb dlho predtým, ako kód vôbec spustíme. The statická analýza využíva množstvo šablón, ktoré sú zostavené so skúsenosťami a porozumenie.

Aj keď je celkom možné len nahliadnuť do kódu a porovnať ho s najlepšími postupmi a pravidlami, ktoré sme vybrali, musíme uznať, že to nie je možné u väčších programov. Existuje však niekoľko nástrojov, ktoré nám umožňujú vykonať túto analýzu. Sú pomerne vyspelé a majú rozsiahlu hruď pravidiel pre väčšinu populárnych programovacích jazykov.

Prevažujúcim nástrojom statickej analýzy pre Javu je FindBugs. FindBugs vyhľadáva prípady „vzorov chýb“. Vzor chyby je idióm kódu, ktorý je často chybou. Môže to vzniknúť z niekoľkých dôvodov, ako sú zložité jazykové vlastnosti, nepochopené metódy a nepochopené invarianty.

FindBugs kontroluje v Java bytecode výskyt vzorov chýb bez skutočného vykonania bytecode. Toto je celkom pohodlné použitie a rýchle spustenie. FindBugs hlási chyby patriace do mnohých kategórií, ako sú podmienky, dizajn a duplikovaný kód.

Zahŕňa tiež chyby súvisiace so súbežnosťou. Je však potrebné poznamenať, že FindBugs môže hlásiť falošné poplachy. V praxi ich je menej, ale musia korelovať s manuálnou analýzou.

5.2. Kontrola modelu

Kontrola modelu je metóda kontroly, či konečný stavový model systému spĺňa danú špecifikáciu. Teraz môže táto definícia znieť príliš akademicky, ale vydržte s ňou chvíľu!

Typicky môžeme výpočtový problém predstavovať ako stroj konečného stavu. Aj keď je to samo o sebe rozsiahla oblasť, dáva nám model s konečnou sadou stavov a pravidlami prechodu medzi nimi s jasne definovanými počiatočnými a koncovými stavmi.

Teraz špecifikácia definuje, ako by sa mal model správať, aby sa mohol považovať za správny. Táto špecifikácia v podstate zodpovedá všetkým požiadavkám systému, ktoré model predstavuje. Jedným zo spôsobov, ako zachytiť špecifikácie, je použitie časovej logickej formuly, ktorú vytvoril Amir Pnueli.

Aj keď je logicky možné vykonať kontrolu modelu ručne, je to dosť nepraktické. Našťastie existuje veľa nástrojov, ktoré nám tu majú pomôcť.Jedným z takýchto nástrojov dostupných pre Javu je Java PathFinder (JPF). JPF bol vyvinutý s dlhoročnými skúsenosťami a výskumom v NASA.

Konkrétne JPF je kontrola modelu pre bajtkód Java. Spustí program všetkými možnými spôsobmi, a tým skontroluje, či vo všetkých možných cestách vykonania nedochádza k porušovaniu vlastností, ako je zablokovanie a nespracované výnimky. Môže sa preto ukázať ako veľmi užitočný pri hľadaní chýb súvisiacich so súbežnosťou v ľubovoľnom programe.

6. Následné úvahy

To by nás už nemalo prekvapovať najlepšie je vyhnúť sa zložitostiam súvisiacim s viacvláknovým kódom toľko koľko je možné. Našim hlavným cieľom by mal byť vývoj programov s jednoduchšími návrhmi, ktoré sa dajú ľahšie testovať a udržiavať. Musíme súhlasiť s tým, že pre súčasné aplikácie je často potrebné súčasné programovanie.

Avšak pri vývoji súbežných programov môžeme prijať niekoľko najlepších postupov a zásad ktoré nám môžu uľahčiť život. V tejto časti si prejdeme niektoré z týchto najlepších postupov, ale mali by sme mať na pamäti, že tento zoznam zďaleka nie je úplný!

6.1. Znížte zložitosť

Zložitosť je faktor, ktorý môže sťažiť testovanie programu aj bez akýchkoľvek súbežných prvkov. Toto sa zlúči tvárou v tvár súbežnosti. Nie je ťažké pochopiť, prečo jednoduchšie a menšie programy sa dajú ľahšie odôvodniť a teda aj efektívne otestovať. Existuje niekoľko najlepších vzorov, ktoré nám tu môžu pomôcť, napríklad SRP (Single Responsibility Pattern) a KISS (Keep It Stupid Simple).

Teraz síce neriešia problém priameho písania testov na súbežný kód, ale uľahčujú pokus o vykonanie úlohy.

6.2. Zvážte atómové operácie

Atómové operácie sú operácie, ktoré fungujú úplne nezávisle na sebe. Preto sa dá jednoducho vyhnúť ťažkostiam s predpovedaním a testovaním vkladania. Porovnanie a výmena je jednou z takýchto široko používaných atómových inštrukcií. Jednoducho povedané, porovnáva obsah pamäťového miesta s danou hodnotou a iba v prípade, že sú rovnaké, upravuje obsah tohto pamäťového miesta.

Väčšina moderných mikroprocesorov ponúka niektoré varianty tejto inštrukcie. Java ponúka celý rad atómových tried ako AtomicInteger a AtomicBoolean, ktorý ponúka výhody pokynov na porovnanie a výmenu.

6.3. Osvojte si nezmeniteľnosť

V programovaní s viacerými vláknami zdieľané údaje, ktoré je možné meniť, vždy nechávajú priestor na chyby. Nezmeniteľnosť odkazuje na stav, keď dátovú štruktúru nie je možné po vytvorení inštancie zmeniť. Toto je zápas vyrobený v nebi pre súčasné programy. Ak stav objektu nie je možné zmeniť po jeho vytvorení, konkurenčné vlákna nebudú musieť o vzájomné vylúčenie požiadať. To výrazne zjednodušuje písanie a testovanie súbežných programov.

Upozorňujeme však, že nie vždy môžeme mať slobodu zvoliť si nemennosť, ale keď je to možné, musíme sa pre ňu rozhodnúť.

6.4. Vyhnite sa zdieľanej pamäti

Väčšina problémov týkajúcich sa programovania viacerých vlákien sa dá pripísať skutočnosti, že máme zdieľanú pamäť medzi konkurenčnými vláknami. Čo keby sme sa ich mohli jednoducho zbaviť! Stále potrebujeme nejaký mechanizmus na komunikáciu vlákien.

Existujú alternatívne návrhové vzory pre súčasné aplikácie, ktoré nám túto možnosť ponúkajú. Jedným z populárnych je herec herec, ktorý hercovi predpisuje základnú jednotku súbežnosti. V tomto modeli interagujú aktéri navzájom zasielaním správ.

Akka je framework napísaný v Scale, ktorý využíva herecký model na ponúkanie lepších primitívov súbežnosti.

7. Záver

V tomto tutoriáli sme sa venovali niektorým základom súvisiacim so súbežným programovaním. Zvlášť podrobne sme diskutovali o viacvláknovej súbežnosti v Jave. Počas testovania takéhoto kódu sme prešli výzvami, ktoré pre nás predstavuje, najmä so zdieľanými údajmi. Ďalej sme prešli niektorými dostupnými nástrojmi a technikami na testovanie súbežného kódu.

Diskutovali sme aj o ďalších spôsoboch, ako sa vyhnúť problémom so súbežnosťou, vrátane nástrojov a techník okrem automatizovaných testov. Nakoniec sme prešli niektorými z najlepších postupov pri programovaní týkajúcich sa súbežného programovania.

Zdrojový kód tohto článku nájdete na GitHub.


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