Skriv ut partall og oddetall ved hjelp av to tråder

1. Introduksjon

I denne opplæringen skal vi se på hvordan vi kan skrive ut partall og oddetall ved hjelp av to tråder.

Målet er å skrive ut tallene i rekkefølge, mens den ene tråden bare skriver ut partallene og den andre tråden bare skriver ut oddetallene. Vi bruker begrepene trådsynkronisering og kommunikasjon mellom tråder for å løse problemet.

2. Tråder i Java

Tråder er lette prosesser som kan utføres samtidig. Samtidig utføring av flere tråder kan være bra når det gjelder ytelse og CPU-bruk, siden vi kan jobbe med mer enn en oppgave samtidig gjennom forskjellige tråder som kjører parallelt.

Mer informasjon om tråder i Java finner du i denne artikkelen.

I Java kan vi lage en tråd ved å enten utvide Tråd klasse eller ved å implementere Kjørbar grensesnitt. I begge tilfeller overstyrer vi løpe metode og skriv implementeringen av tråden i den.

Mer informasjon om hvordan du bruker disse metodene til å lage en tråd finner du her.

3. Trådsynkronisering

I et miljø med flere tråder er det mulig at to eller flere tråder får tilgang til samme ressurs omtrent samtidig. Dette kan være dødelig og føre til feilaktige resultater. For å forhindre dette, må vi sørge for at bare en tråd får tilgang til ressursen på et gitt tidspunkt.

Vi kan oppnå dette ved hjelp av trådsynkronisering.

I Java kan vi markere en metode eller blokk som synkronisert, noe som betyr at bare en tråd vil være i stand til å gå inn i den metoden eller blokkere på et gitt tidspunkt.

Mer informasjon om trådsynkronisering i Java finner du her.

4. Kommunikasjon mellom tråder

Inter-thread-kommunikasjon lar synkroniserte tråder kommunisere med hverandre ved hjelp av et sett med metoder.

Metodene som brukes er vente, gi beskjed, og varsle alle, som alle er arvet fra Gjenstand klasse.

Vente() får den gjeldende tråden til å vente på ubestemt tid til noen andre tråder ringer notify () or notifyAll () på samme objekt. Vi kan ringe gi beskjed() å vekke tråder som venter på tilgang til objektets skjerm.

Flere detaljer om hvordan disse metodene fungerer, finner du her.

5. Skrive ut oddetall og jevne tall alternativt

5.1. Ved hjelp av vente() og gi beskjed()

Vi vil bruke de diskuterte begrepene synkronisering og kommunikasjon mellom tråder for å skrive ut oddetall og partall i stigende rekkefølge ved hjelp av to forskjellige tråder.

I det første trinnet implementerer vi Kjørbar grensesnitt for å definere logikken til begge trådene. I løpe metode, sjekker vi om tallet er jevnt eller odde.

Hvis tallet er jevnt, kaller vi printEven metoden for Skriver klasse, ellers kaller vi printOdd metode:

klasse TaskEvenOdd implementerer Runnable {private int max; privat utskrift av skrivere; privat boolsk isEvenNumber; // standardkonstruktører @ Override public void run () {int number = isEvenNumber? 2: 1; while (number <= max) {if (isEvenNumber) {print.printEven (number); } annet {print.printOdd (nummer); } nummer + = 2; }}} 

Vi definerer Skriver klasse som følger:

klasse Skriver {privat flyktig boolsk isOdd; synkronisert ugyldig printEven (int nummer) {mens (! isOdd) {prøv {vent (); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); }} System.out.println (Thread.currentThread (). GetName () + ":" + nummer); isOdd = falsk; gi beskjed(); } synkronisert ugyldig printOdd (int-nummer) {while (isOdd) {try {wait (); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); }} System.out.println (Thread.currentThread (). GetName () + ":" + nummer); isOdd = sant; gi beskjed(); }}

I hovedmetoden bruker vi den definerte klassen til å lage to tråder. Vi lager et objekt av Skriver klasse og sende den som parameter til TaskEvenOdd konstruktør:

public static void main (String ... args) {Skriverutskrift = ny skriver (); Tråd t1 = ny tråd (ny TaskEvenOdd (utskrift, 10, usann), "Odd"); Tråd t2 = ny tråd (ny TaskEvenOdd (utskrift, 10, sann), "Jevn"); t1.start (); t2.start (); }

Den første tråden vil være den merkelige tråden, derfor passerer vi falsk som verdien av parameteren erEvenNumber. For den andre tråden passerer vi ekte i stedet. Vi setter maxValue til 10 for begge trådene, slik at bare tallene fra 1 til 10 skrives ut.

Vi starter deretter begge trådene med å kalle start() metode. Dette vil påkalle løpe() metode for begge trådene som definert ovenfor, hvor vi sjekker om tallet er oddetall eller jevnt og skriver dem ut.

Når den odde tråden begynner å løpe, blir verdien av variabelen Nummer vil være 1. Siden det er mindre enn maxValue og flagget erEvenNumber er falsk, printOdd () er kalt. I metoden sjekker vi om flagget erOdd er sant, og mens det er sant, kaller vi vente(). Siden erOdd er opprinnelig falsk, vente() kalles ikke, og verdien skrives ut.

Vi setter deretter verdien av erOdd til sant, slik at den odde tråden går i ventetilstand og ringer gi beskjed() å vekke den jevne tråden. Den jevne tråden våkner så opp og skriver ut partall siden merkelig flagget er falskt. Det kaller da gi beskjed() å vekke den rare tråden.

Den samme prosessen utføres til verdien av variabelen Nummer er større enn maxValue.

5.2. Bruke semaforer

En semafor styrer tilgangen til en delt ressurs ved bruk av en teller. Hvis den telleren er større enn null, da er tilgang tillatt. Hvis det er null, nektes tilgang.

Java tilbyr Semafor klasse i java.util.concurrent pakken, og vi kan bruke den til å implementere den forklarte mekanismen. Flere detaljer om semaforer finner du her.

Vi lager to tråder, en merkelig tråd og en jevn tråd. Den odde tråden vil skrive ut oddetallene som starter fra 1, og den jevne tråden vil skrive ut de partallene som starter fra 2.

Begge trådene har et objekt av Delt skriver klasse. De Delt skriver klassen vil ha to semaforer, semOdd og semEven som vil ha 1 og 0 tillatelser til å begynne med. Dette vil sikre at oddetall blir skrevet ut først.

Vi har to metoder printEvenNum () og printOddNum (). Den merkelige tråden kaller printOddNum () metode og jevn tråd kaller printEvenNum () metode.

For å skrive ut et oddetall, tilegne() metoden kalles på semOdd, og siden den opprinnelige tillatelsen er 1, får den tilgangen vellykket, skriver ut oddetallet og ringer utgivelse()semEven.

Ringer utgivelse() vil øke tillatelsen med 1 for semEven, og den jevne tråden kan da med hell skaffe tilgang og skrive ut partallnummeret.

Dette er koden for arbeidsflyten beskrevet ovenfor:

public static void main (String [] args) {SharedPrinter sp = new SharedPrinter (); Tråd odd = ny tråd (ny Odd (sp, 10), "Odd"); Tråd jevn = ny tråd (ny jevn (sp, 10), "jevn"); odd.start (); even.start (); }
klasse SharedPrinter {private Semaphore semEven = new Semaphore (0); privat Semaphore semOdd = ny Semaphore (1); ugyldig printEvenNum (int num) {prøv {semEven.acquire (); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); } System.out.println (Thread.currentThread (). GetName () + num); semOdd.release (); } ugyldig printOddNum (int num) {prøv {semOdd.acquire (); } fange (InterruptedException e) {Thread.currentThread (). interrupt (); } System.out.println (Thread.currentThread (). GetName () + num); semEven.release (); }} klasse Selv implementerer Runnable {private SharedPrinter sp; privat int max; // standardkonstruktør @ Overstyr offentlig tomromkjøring () {for (int i = 2; i <= max; i = i + 2) {sp.printEvenNum (i); }}} klasse Odd implementerer Runnable {private SharedPrinter sp; privat int max; // standardkonstruktører @ Overstyr offentlig ugyldig kjøring () {for (int i = 1; i <= max; i = i + 2) {sp.printOddNum (i); }}}

6. Konklusjon

I denne opplæringen så vi på hvordan vi kan skrive ut oddetall og partall, alternativt ved hjelp av to tråder i Java. Vi så på to metoder for å oppnå de samme resultatene: ved hjelp av vente() og gi beskjed() og bruker en Semafor.

Og som alltid er den fullstendige arbeidskoden tilgjengelig på GitHub.


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