Tlačte párne a nepárne čísla pomocou 2 vlákien

1. Úvod

V tomto výučbe sa pozrieme na to, ako môžeme tlačiť párne a nepárne čísla pomocou dvoch vlákien.

Cieľom je vytlačiť čísla v poradí, zatiaľ čo jedno vlákno vytlačí iba párne čísla a druhé vlákno iba nepárne čísla. Na vyriešenie problému použijeme koncepty synchronizácie vlákien a medzivláknovej komunikácie.

2. Vlákna v Jave

Vlákna sú ľahké procesy, ktoré je možné vykonávať súčasne. Súbežné vykonávanie viacerých vlákien môže byť dobré, pokiaľ ide o výkon a využitie procesora, pretože môžeme pracovať na viacerých úlohách naraz prostredníctvom rôznych vlákien, ktoré bežia paralelne.

Viac informácií o vláknach v prostredí Java nájdete v tomto článku.

V Jave môžeme vlákno vytvoriť rozšírením Závit triedy alebo implementáciou Spustiteľné rozhranie. V obidvoch prípadoch prepíšeme bežať metóda a zapíše do nej implementáciu vlákna.

Viac informácií o tom, ako použiť tieto metódy na vytvorenie vlákna, nájdete tu.

3. Synchronizácia vlákna

V prostredí s viacerými vláknami je možné, že 2 alebo viac vlákien pristupuje k rovnakému prostriedku v rovnakom čase. Môže to byť fatálne a viesť k chybným výsledkom. Aby sme tomu zabránili, musíme sa ubezpečiť, že k zdroju má v danom okamihu prístup iba jedno vlákno.

To môžeme dosiahnuť pomocou synchronizácie vlákien.

V Jave môžeme metódu alebo blok označiť ako synchronizované, čo znamená, že do tejto metódy alebo bloku bude môcť v danom okamihu vstúpiť iba jedno vlákno.

Viac podrobností o synchronizácii vlákien v Jave nájdete tu.

4. Komunikácia medzi vláknami

Komunikácia medzi vláknami umožňuje synchronizovaným vláknam navzájom komunikovať pomocou sady metód.

Použité metódy sú počkaj, upozorniť, a notifyAll, ktoré sa všetky dedia z Objekt trieda.

Počkajte () spôsobí, že súčasné vlákno bude čakať neurčito, kým zavolá nejaké iné vlákno notify () alebo notifyAll () na rovnakom objekte. Môžeme zavolať upozorniť () prebudiť vlákna, ktoré čakajú na prístup k monitoru tohto objektu.

Viac podrobností o fungovaní týchto metód nájdete tu.

5. Alternatívna tlač nepárnych a párnych čísel

5.1. Použitím počkaj () a upozorniť ()

Diskutované koncepty synchronizácie a medzivláknovej komunikácie použijeme na tlač nepárnych a párnych čísel vo vzostupnom poradí pomocou dvoch rôznych vlákien.

V prvom kroku implementujeme Spustiteľné rozhranie na definovanie logiky oboch vlákien. V bežať metódou skontrolujeme, či je číslo párne alebo nepárne.

Ak je číslo párne, hovoríme printEven metóda Tlačiareň triedy, inak hovoríme printOdd metóda:

trieda TaskEvenOdd implementuje Runnable {private int max; tlač súkromnej tlačiarne; private boolean isEvenNumber; // štandardné konštruktory @Override public void run () {int number = isEvenNumber? 2: 1; while (number <= max) {if (isEvenNumber) {print.printEven (number); } else {print.printOdd (cislo); } číslo + = 2; }}} 

Definujeme Tlačiareň triedy nasledovne:

trieda Printer {private volatile boolean isOdd; synchronized void printEven (int number) {while (! isOdd) {try {wait (); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); }} System.out.println (Thread.currentThread (). GetName () + ":" + číslo); isOdd = false; oznámiť (); } synchronized void printOdd (int number) {while (isOdd) {try {wait (); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); }} System.out.println (Thread.currentThread (). GetName () + ":" + číslo); isOdd = true; oznámiť (); }}

V hlavnej metóde používame definovanú triedu na vytvorenie dvoch vlákien. Vytvárame objekt Tlačiareň triedy a odovzdať ju ako parameter do TaskEvenOdd konštruktér:

public static void main (String ... args) {Printer print = new Printer (); Vlákno t1 = nové vlákno (nové TaskEvenOdd (tlač, 10, nepravda), "nepárne"); Vlákno t2 = nové vlákno (nové TaskEvenOdd (tlač, 10, pravda), "párne"); t1.start (); t2.start (); }

Prvé vlákno bude nepárne vlákno, a preto ho odovzdáme nepravdivé ako hodnota parametra isEvenNumber. Pre druhé vlákno minieme pravda namiesto toho. Nastavili sme maxValue na 10 pre obe vlákna, takže sa vytlačia iba čísla od 1 do 10.

Potom začneme obe vlákna volaním znaku štart () metóda. Toto vyvolá run () metóda oboch vlákien, ako je definované vyššie, pričom skontrolujeme, či je počet nepárny alebo párny, a vytlačíme ich.

Keď sa spustí nepárne vlákno, hodnota premennej číslo bude 1. Pretože je to menej ako maxValue a vlajka isEvenNumber je nepravdivé, printOdd () sa volá. V metóde skontrolujeme, či je príznak isOdd je pravda a aj keď je to pravda, hovoríme počkaj (). Odkedy isOdd je spočiatku nepravdivé, počkaj () sa nezavolá a hodnota sa vytlačí.

Potom sme nastavili hodnotu isOdd na true, takže nepárne vlákno prejde do stavu čakania a zavolá upozorniť () prebudiť rovnomernú niť. Rovnomerné vlákno sa potom prebudí a vytlačí párne číslo od zvláštny vlajka je nepravdivá. Potom zavolá upozorniť () prebudiť nepárne vlákno.

Rovnaký proces sa vykonáva až do hodnoty premennej číslo je väčšie ako maxValue.

5.2. Pomocou Semaforov

Semafor riadi prístup k zdieľanému prostriedku pomocou počítadla. Ak Počítadlo je väčšie ako nula, potom je povolený prístup. Ak je nula, potom je prístup zamietnutý.

Java poskytuje Semafor trieda v java.util.concurrent balíka a môžeme ho použiť na implementáciu vysvetleného mechanizmu. Viac podrobností o semaforoch nájdete tu.

Vytvoríme dve vlákna, nepárne vlákno a párne vlákno. Nepárne vlákno vytlačí nepárne čísla začínajúce od 1 a párne vlákno vytlačí párne čísla začínajúce od 2.

Obe vlákna majú predmet SharedPrinter trieda. The SharedPrinter trieda bude mať dve semafory, semOdd a semEven ktoré budú mať na začiatku 1 a 0 povolení. Takto zabezpečíte, že sa najskôr vytlačí nepárne číslo.

Máme dve metódy printEvenNum () a printOddNum (). Nepárne vlákno nazýva printOddNum () metóda a rovnomerné vlákno volá printEvenNum () metóda.

Ak chcete vytlačiť nepárne číslo, stlačte získať () metóda je vyvolaná semOdd, a keďže počiatočné povolenie je 1, úspešne získava prístup, tlačí nepárne číslo a volá uvoľniť () na semEven.

Telefonovanie uvoľniť () zvýši povolenie o 1 pre semEven, a párne vlákno potom môže úspešne získať prístup a vytlačiť párne číslo.

Toto je kód vyššie popísaného pracovného postupu:

public static void main (String [] args) {SharedPrinter sp = new SharedPrinter (); Vlákno nepárne = nové vlákno (nové nepárne (sp, 10), "nepárne"); Vlákno párne = nové Vlákno (nové párne (sp, 10), "párne"); odd.start (); even.start (); }
trieda SharedPrinter {súkromný semafor semEven = nový semafor (0); súkromný semafor semOdd = nový semafor (1); void printEvenNum (int num) {try {semEven.acquire (); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); } System.out.println (Thread.currentThread (). GetName () + num); semOdd.release (); } void printOddNum (int num) {try {semOdd.acquire (); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); } System.out.println (Thread.currentThread (). GetName () + num); semEven.release (); }} trieda Dokonca implementuje Runnable {private SharedPrinter sp; súkromné ​​int max; // štandardný konštruktor @Override public void run () {for (int i = 2; i <= max; i = i + 2) {sp.printEvenNum (i); }}} trieda Odd implementuje Runnable {private SharedPrinter sp; súkromné ​​int max; // štandardné konštruktory @Override public void run () {for (int i = 1; i <= max; i = i + 2) {sp.printOddNum (i); }}}

6. Záver

V tomto tutoriáli sme sa pozreli na to, ako môžeme tlačiť nepárne a párne čísla alternatívne pomocou dvoch vlákien v Jave. Pozreli sme sa na dve metódy, aby sme dosiahli rovnaké výsledky: použitím počkaj () a upozorniť () a pomocou a Semafor.

Celý pracovný kód je ako vždy k dispozícii na GitHub.


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