4 Metoder for å skrive multi-threaded kode i Java
Multi-threading er en metode for å skrive kode for å utføre oppgaver parallelt. Java har hatt utmerket støtte for å skrive multi-threaded kode siden de første dagene av Java 1.0. Nylige forbedringer til Java har økt måtene i hvilken kode kan struktureres for å inkorporere multi-threading i Java-programmer.
I denne artikkelen sammenligner vi noen av disse alternativene, slik at du bedre kan bedømme hvilket alternativ du vil bruke til din neste Java Projec Love GitHub? 4 grunner til at du bør være vert for koden din på BitBucket Love GitHub? 4 grunner til at du bør være vert for koden din på BitBucket Du må tenke på hvor du har tenkt å lagre koden din. Det er sannsynlig at du har hørt om GitHub. Det er ikke overraskende. GitHub brukes av enkeltpersoner og bedrifter til vertskode, samarbeider om dokumentasjon ... Les mer t.
Metode 1: Utvide tråkklassen
Java gir en Tråd klasse som kan utvides til å implementere løpe() metode. Denne run () -metoden er der du implementerer oppgaven din. Når du vil sparke oppgaven i sin egen tråd, kan du opprette en forekomst av denne klassen og påkalle den start() metode. Dette starter gjennomføringen av tråden og kjører til ferdigstillelse (eller avsluttes i et unntak).
Her er en enkel trådklasse som bare sover for et spesifisert intervall som en måte å simulere en langvarig drift på.
offentlig klasse MyThread utvider tråden private int sleepFor; offentlig MyThread (int sleepFor) this.sleepFor = sleepFor; @Override public void run () System.out.printf ("[% s] tråden starter \ n", Thread.currentThread (). ToString ()); prøv Thread.sleep (this.sleepFor); fangst (InterruptedException ex) System.out.printf ("[% s] tråden slutter \ n", Thread.currentThread (). toString ());
Opprett en forekomst av denne tråkklassen ved å gi det antall millisekunder å sove.
MyThread worker = new MyThread (sleepFor);
Kikk ut avføringen av denne arbeiderens tråd ved å påkalle sin start () -metode. Denne metoden returnerer kontrollen umiddelbart til den som ringer, uten å vente på at tråden skal avslutte.
worker.start (); System.out.printf ("[% s] hovedtråd \ n", Thread.currentThread (). ToString ());
Og her er produksjonen fra å kjøre denne koden. Det indikerer at hovedtråddiagnosen skrives ut før arbeidstrådens tråd utføres.
[Tråd [hoved, 5, hoved]] tråd [Tråd [Tråd-0,5, hoved]] tråd starter [Tråd [Tråd-0,5, hoved]] trådende
Siden det ikke er flere utsagn etter å ha startet arbeidstråden, venter hovedtråden for at arbeidstrådens tråden skal avsluttes før programmet går ut. Dette tillater arbeideren tråden å fullføre oppgaven sin.
Metode 2: Ved hjelp av en gjengemøte med en runnable
Java gir også et grensesnitt kalt kjørbart som kan implementeres av en arbeiderklasse for å utføre oppgaven i sin løpe() metode. Dette er en alternativ måte å skape en arbeiderklasse i motsetning til å utvide Tråd klasse (beskrevet ovenfor).
Her er implementeringen av arbeiderklassen som nå implementerer Runnable i stedet for å utvide Thread.
offentlig klasse MyThread2 implementerer Runnable // samme som ovenfor
Fordelen med å implementere Runnable-grensesnittet i stedet for å utvide Thread-klassen er at arbeiderklassen nå kan utvide en domenespesifikk klasse i et klasses hierarki.
Hva betyr dette?
La oss si at du for eksempel har en Frukt klasse som implementerer visse generiske egenskaper av frukt. Nå vil du implementere en papaya klassen som spesialiserer seg på enkelte fruktkarakteristikker. Du kan gjøre det ved å ha papaya klassen forlenge Frukt klasse.
offentlig klasse Frukt // fruktsspesifikke her offentlig klasse Papaya utvider frukt // overstyringsadferd spesifikk for papaya her
Anta nå at du har en tidkrevende oppgave som Papaya trenger å støtte, som kan utføres i en egen tråd. Denne saken kan håndteres ved å ha Papaya-klassen implementere Runnable og gi run () -metoden der denne oppgaven utføres.
offentlig klasse Papaya utvider fruktredskaper Runnable // override behavior spesifikt for papaya her @Override public void run () // tidkrevende oppgave her.
For å sparke arbeidstakerens tråd, oppretter du en forekomst av arbeiderklassen og overleverer den til en Thread-forekomst ved opprettelsen. Når start () -metoden til tråden er påkalt, utføres oppgaven i en egen tråd.
Papaya Papaya = Ny Papaya (); // sett egenskaper og påkall papaya metoder her. Tråd = Ny tråd (Papaya); thread.start ();
Og det er en kort oppsummering av hvordan du bruker en Runnable å implementere en oppgave som utfører i en tråd.
Metode 3: Utfør en løpbar med ExecutorService
Fra og med versjon 1.5 gir Java en ExecutorService som et nytt paradigme for å skape og administrere tråder i et program. Det generaliserer konseptet med trådkjøp ved å trekke bort trådenes skapelse.
Dette skyldes at du kan kjøre oppgavene dine i et trådtråd like enkelt som å bruke en egen tråd for hver oppgave. Dette gjør at programmet kan spore og styre hvor mange tråder som brukes til arbeidstakeroppgaver.
Anta at du har 100 arbeideroppgaver som venter på å bli henrettet. Hvis du starter en tråd per arbeidstaker (som vist ovenfor), vil du ha 100 tråder i programmet, noe som kan føre til flaskehalser andre steder i programmet. I stedet, hvis du bruker et trådbad med, si 10 tråder som er forhåndsallokert, vil dine 100 oppgaver bli utført av disse tråder en etter en, slik at programmet ikke sulter for ressurser. I tillegg kan disse trådbadetrådene konfigureres slik at de henger rundt for å utføre flere oppgaver for deg.
En ExecutorService godtar a kjørbart oppgave (forklart ovenfor) og kjører oppgaven på et passende tidspunkt. De sende inn() metode, som aksepterer Runnable-oppgaven, returnerer en forekomst av en klasse som kalles Framtid, som tillater den som ringer å spore status for oppgaven. Spesielt, den få() Metoden tillater den som ringer til å vente på oppgaven å fullføre (og gir returkoden, om noen).
I eksemplet nedenfor oppretter vi en ExecutorService ved hjelp av den statiske metoden newSingleThreadExecutor (), som som navnet indikerer, oppretter en enkelt tråd for å utføre oppgaver. Hvis flere oppgaver sendes mens en oppgave kjører, kjøper ExecutorService disse oppgavene for senere utførelse.
Runnable-implementeringen vi bruker her er den samme som beskrevet ovenfor.
ExecutorService esvc = Executors.newSingleThreadExecutor (); Runnable worker = new MyThread2 (sleepFor); Framtid> fremtid = esvc.submit (arbeidstaker); System.out.printf ("[% s] hovedtråd \ n", Thread.currentThread (). ToString ()); future.get (); esvc.shutdown ();
Merk at en ExecutorService må være ordentlig slått av når den ikke lenger er nødvendig for ytterligere oppgaveoppgaver.
Metode 4: En Callable Brukes Med ExecutorService
Fra og med versjon 1.5, introduserte Java et nytt grensesnitt Callable. Det ligner på det eldre Runnable-grensesnittet med forskjellen mellom utførelsesmetoden (kalles anrop() i stedet for løpe()) kan returnere en verdi. I tillegg kan det også erklære at en Unntak kan kastes.
En ExecutorService kan også akseptere oppgaver som er implementert som Callable og returnerer a Framtid med verdien returnert av metoden ved ferdigstillelse.
Her er et eksempel Mango klasse som strekker seg Frukt klassen definert tidligere og implementerer Callable grensesnitt. En dyr og tidkrevende oppgave utføres innenfor anrop() metode.
offentlig klasse Mango utvider fruktredskaper Callable public Integer call () // dyre beregning her returner nytt heltall (0);
Og her er koden for å sende en forekomst av klassen til en ExecutorService. Koden nedenfor venter også på oppgaven å fullføre og skrive ut returverdien.
ExecutorService esvc = Executors.newSingleThreadExecutor (); MyCallable worker = new MyCallable (sleepFor); Fremtidens fremtid = esvc.submit (worker); System.out.printf ("[% s] hovedtråd \ n", Thread.currentThread (). ToString ()); System.out.println ("Oppgave returnert:" + future.get ()); esvc.shutdown ();
Hva foretrekker du?
I denne artikkelen lærte vi noen få metoder for å skrive multi-threaded kode i Java. Disse inkluderer:
- Utvide Tråd klassen er den mest grunnleggende og har vært tilgjengelig fra Java 1.0.
- Hvis du har en klasse som må utvide en annen klasse i et klasses hierarki, kan du implementere kjørbart grensesnitt.
- Et mer moderne anlegg for å lage tråder er ExecutorService som kan akseptere en Runnable-instans som en oppgave å kjøre. Fordelen med denne metoden er at du kan bruke et trådbasseng for oppgaveutførelse. Et trådbasseng hjelper til med ressursbevarelse ved å gjenbruke tråder.
- Til slutt kan du også opprette en oppgave ved å implementere Callable grensesnitt og sende oppgaven til en ExecutorService.
Hvilke av disse alternativene tror du at du vil bruke i ditt neste prosjekt? Gi oss beskjed i kommentarene nedenfor.
Utforsk mer om: Java.