Ispis parnih i neparnih brojeva pomoću 2 niti

1. Uvod

U ovom uputstvu ćemo pogledati kako možemo ispisati parne i neparne brojeve pomoću dvije niti.

Cilj je ispisati brojeve redom, dok jedna nit ispisuje samo parne brojeve, a druga nit samo neparne brojeve. Za rješavanje problema koristit ćemo koncepte sinkronizacije niti i međusobne komunikacije.

2. Niti u Javi

Niti su lagani procesi koji se mogu istodobno izvršavati. Istodobno izvršavanje više niti može biti dobro s obzirom na performanse i upotrebu CPU-a jer možemo raditi na više zadataka odjednom kroz različite niti koje se paralelno izvode.

Više informacija o nitima u Javi možete pronaći u ovom članku.

U Javi možemo stvoriti nit proširivanjem datoteke Nit klase ili primjenom Izvodljivo sučelje. U oba slučaja nadjačavamo trčanje metodu i u nju napišite implementaciju niti.

Više informacija o tome kako koristiti ove metode za stvaranje niti možete pronaći ovdje.

3. Sinkronizacija niti

U okruženju s više niti moguće je da 2 ili više niti pristupaju istom resursu otprilike u isto vrijeme. To može biti kobno i dovesti do pogrešnih rezultata. Da bismo to spriječili, moramo osigurati da samo jedna nit pristupa resursu u određenom trenutku.

To možemo postići pomoću sinkronizacije niti.

U Javi možemo označiti metodu ili blok kao sinkronizirane, što znači da će samo jedna nit moći ući u tu metodu ili blok u određenom trenutku.

Više detalja o sinkronizaciji niti u Javi možete pronaći ovdje.

4. Komunikacija između niti

Komunikacija među nitima omogućuje sinkroniziranim nitima da međusobno komuniciraju pomoću skupa metoda.

Korištene metode su čekati, obavijestiti, i notifyAll, koji su svi naslijeđeni od Objekt razred.

Čekati() uzrokuje da trenutna nit čeka neograničeno dok neka druga nit ne pozove notify () ili notifyAll () na istom objektu. Možemo nazvati obavijestiti() na buđenje niti koje čekaju pristup monitoru ovog objekta.

Više detalja o radu ovih metoda možete pronaći ovdje.

5. Alternativno ispisivanje neparnih i parnih brojeva

5.1. Koristeći čekati() i obavijestiti()

Upotrijebit ćemo raspravljene koncepte sinkronizacije i međusobne komunikacije za ispis neparnih i parnih brojeva uzlaznim redoslijedom pomoću dvije različite niti.

U prvom koraku implementirat ćemo Izvodljivo sučelje za definiranje logike obje niti. U trčanje metodom provjeravamo je li broj paran ili neparan.

Ako je broj paran, zovemo printEven metoda Pisač razred, inače nazivamo printOdd metoda:

klasa TaskEvenOdd implementira Runnable {private int max; privatni Printer print; private boolean isEvenNumber; // standardni konstruktori @Preuzmi javnu void run () {int broj = isEvenNumber? 2: 1; while (broj <= max) {if (isEvenNumber) {print.printEven (broj); } else {print.printOdd (broj); } broj + = 2; }}} 

Mi definiramo Pisač razred kako slijedi:

class Printer {private volatile boolean isOdd; sinkronizirani void printEven (int broj) {while (! isOdd) {try {wait (); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); }} System.out.println (Thread.currentThread (). GetName () + ":" + broj); isOdd = lažno; obavijestiti(); } sinkronizirani void printOdd (int broj) {while (isOdd) {try {wait (); } catch (InterruptedException e) {Thread.currentThread (). interrupt (); }} System.out.println (Thread.currentThread (). GetName () + ":" + broj); isOdd = true; obavijestiti(); }}

U glavnoj metodi koristimo definiranu klasu za stvaranje dviju niti. Mi stvaramo objekt Pisač klase i proslijedite ga kao parametar u TaskEvenOdd konstruktor:

public static void main (String ... args) {Printer print = novi pisač (); Tema t1 = nova nit (nova TaskEvenOdd (print, 10, false), "Nepar"); Tema t2 = nova nit (nova TaskEvenOdd (print, 10, true), "Even"); t1.start (); t2.start (); }

Prva nit bit će neparna nit, stoga prolazimo lažno kao vrijednost parametra isEvenNumber. Za drugu nit prolazimo pravi umjesto toga. Postavili smo maxValue do 10 za obje niti, tako da se ispisuju samo brojevi od 1 do 10.

Zatim započinjemo obje niti pozivanjem znaka početak() metoda. Ovo će pozvati trčanje() metoda obje niti kako je gore definirano pri čemu provjeravamo je li broj neparan ili paran i ispisujemo ih.

Kada se neparna nit počne izvoditi, vrijednost varijable broj bit će 1. Budući da je manje od maxValue i zastava isEvenNumber je lažno, printOdd () Zove se. U metodi provjeravamo je li zastava isOdd je istina i dok je istina mi zovemo čekati(). Od isOdd je lažno u početku, čekati() se ne poziva, a vrijednost se ispisuje.

Zatim postavljamo vrijednost isOdd na true, tako da neparna nit prelazi u stanje čekanja i poziva obavijestiti() probuditi ujednačenu nit. Parna nit se zatim budi i ispisuje paran broj od neparan zastava je lažna. Zatim poziva obavijestiti() da se probudi neparna nit.

Isti se postupak provodi do vrijednosti varijable broj je veći od maxValue.

5.2. Korištenje semafora

Semafor kontrolira pristup zajedničkom resursu pomoću brojača. Ako je brojač veći od nule, tada je pristup dopušten. Ako je nula, pristup je odbijen.

Java nudi Semafor razred u java.util.concurrent paket i pomoću njega možemo primijeniti objašnjeni mehanizam. Više detalja o semaforima možete pronaći ovdje.

Stvorimo dvije niti, neparnu i parnu nit. Neparni konac ispisivao bi neparne brojeve počevši od 1, a parni konac ispisivao bi parne brojeve koji počinju od 2.

Obje niti imaju objekt SharedPrinter razred. The SharedPrinter razred će imati dva semafora, semOdd i semEven koja će za početak imati dozvole 1 i 0. To će osigurati da se neparni broj prvo ispiše.

Imamo dvije metode printEvenNum () i printOddNum (). Neparna nit poziva printOddNum () metoda, a niti even poziva printEvenNum () metoda.

Za ispis neparnog broja, steći() metoda se poziva na semOdd, a budući da je početna dozvola 1, pristup uspješno stječe, ispisuje neparan broj i poziva otpustiti () na semEven.

Pozivanje otpustiti () će povećati dozvolu za 1 for semEven, a parna nit tada može uspješno steći pristup i ispisati parni broj.

Ovo je kod za gore opisani tijek rada:

javna statička void glavna (String [] args) {SharedPrinter sp = novi SharedPrinter (); Tema neparna = nova nit (nova Neparna (sp, 10), "Neparna"); Thread even = nova nit (new Even (sp, 10), "Even"); odd.start (); even.start (); }
klasa SharedPrinter {privatni Semafor semEven = novi Semafor (0); privatni Semafor semOdd = novi 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 (); }} klasa Čak implementira Runnable {private SharedPrinter sp; privatni int max; // standardni konstruktor @Override public void run () {for (int i = 2; i <= max; i = i + 2) {sp.printEvenNum (i); }}} klasa Odd implementira Runnable {private SharedPrinter sp; privatni int max; // standardni konstruktori @Override public void run () {for (int i = 1; i <= max; i = i + 2) {sp.printOddNum (i); }}}

6. Zaključak

U ovom smo tutorijalu pogledali kako alternativno možemo ispisivati ​​neparne i parne brojeve pomoću dvije niti u Javi. Pregledali smo dvije metode za postizanje istih rezultata: koristeći čekati() i obavijestiti() i pomoću a Semafor.

I kao i uvijek, puni radni kod dostupan je na GitHubu.


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