Multithreading-in Java
Elke applicatie kan meerdere processen (instances) hebben. Elk van deze processen kan worden toegewezen als een enkele thread of meerdere threads. In deze tutorial zullen we zien hoe we meerdere taken tegelijkertijd kunnen uitvoeren en ook meer leren over threads en synchronisatie tussen threads.
Wat is enkele draad?
Eén draadje erin Java is in feite een lichtgewicht en de kleinste verwerkingseenheid. Java gebruikt threads door gebruik te maken van een “Thread Class”. Er zijn twee soorten threads – gebruikersthread en daemonthread (daemon threads worden gebruikt wanneer we de applicatie willen opschonen en worden op de achtergrond gebruikt). Wanneer een applicatie voor het eerst start, wordt er een user thread aangemaakt. Daarna kunnen we veel user threads en daemon threads aanmaken.
Voorbeeld met enkele draad:
package demotest; public class GuruThread { public static void main(String[] args) { System.out.println("Single Thread"); } }
Voordelen van enkele draad:
- Vermindert de overhead in de applicatie omdat er een enkele thread in het systeem wordt uitgevoerd
- Bovendien verlaagt het de onderhoudskosten van de applicatie.
Wat is multithreading? Java?
multithreading in Java is een proces van het uitvoeren van twee of meer threads tegelijk om de CPU maximaal te benutten. Multithreaded applicaties voeren twee of meer threads tegelijk uit. Daarom staat het ook bekend als Concurrency in Java. Elke draad loopt parallel aan elkaar. Meerdere threads wijzen geen afzonderlijk geheugengebied toe en besparen daarom geheugen. Bovendien kost het wisselen van context tussen threads minder tijd.
Voorbeeld van multi-thread:
package demotest; public class GuruThread1 implements Runnable { public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
Voordelen van multithread:
- De gebruikers worden niet geblokkeerd omdat de threads onafhankelijk zijn en we meerdere bewerkingen tegelijk kunnen uitvoeren
- Als zodanig zijn de threads onafhankelijk en worden de andere threads niet beïnvloed als een thread aan een uitzondering voldoet.
Levenscyclus inpassen Java
De levenscyclus van een thread:
Er zijn verschillende fasen in de levenscyclus van draad, zoals weergegeven in het bovenstaande diagram:
- Nieuw
- uitvoerbare
- Hardlopen
- Het wachten
- Dood
- Nieuw: In deze fase wordt de thread gemaakt met behulp van de klasse "Thread class". Deze blijft in deze staat tot het programma starts de draad. Het wordt ook wel geboren draad genoemd.
- Uitvoerbaar: Op deze pagina wordt het exemplaar van de thread aangeroepen met een startmethode. De threadcontrole wordt aan de planner gegeven om de uitvoering te voltooien. Het hangt van de planner af of de thread moet worden uitgevoerd.
- running: Wanneer de thread wordt uitgevoerd, wordt de status gewijzigd in de status 'actief'. De planner selecteert één thread uit de threadpool en begint met uitvoeren in de applicatie.
- Aan het wachten: Dit is de status waarin een thread moet wachten. Omdat er meerdere threads in de applicatie draaien, is er behoefte aan synchronisatie tussen threads. Daarom moet de ene thread wachten totdat de andere thread wordt uitgevoerd. Daarom wordt deze status aangeduid als wachtstatus.
- Dood: Dit is de status wanneer de thread wordt beëindigd. De thread bevindt zich in de actieve status en zodra de verwerking is voltooid, bevindt deze zich in de "dode status".
Methoden voor multithreading in Java
Enkele veelgebruikte methoden voor threads zijn:Methode | BESCHRIJVING |
---|---|
begin() | Deze methode start de uitvoering van de thread en JVM roept de run() -methode op de thread aan. |
Slaap(int milliseconden) | Deze methode zorgt ervoor dat de thread slaapt, waardoor de uitvoering van de thread milliseconden pauzeert en daarna weer start met uitvoeren. Dit helpt bij de synchronisatie van de threads. |
getName () | Het retourneert de naam van de thread. |
setPriority(int nieuweprioriteit) | Het verandert de prioriteit van de thread. |
opbrengst () | Het zorgt ervoor dat de huidige thread wordt stopgezet en dat andere threads worden uitgevoerd. |
Voorbeeld: In dit multithreading-programma in Java We gaan bijvoorbeeld een thread maken en de ingebouwde methoden verkennen die beschikbaar zijn voor threads.
package demotest; public class thread_example1 implements Runnable { @Override public void run() { } public static void main(String[] args) { Thread guruthread1 = new Thread(); guruthread1.start(); try { guruthread1.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } guruthread1.setPriority(1); int gurupriority = guruthread1.getPriority(); System.out.println(gurupriority); System.out.println("Thread Running"); } }
Uitleg van de code:
- Coderegel 2: We maken een klasse "thread_Example1" die de Runnable-interface implementeert (deze moet worden geïmplementeerd door elke klasse waarvan de instanties bedoeld zijn om door de thread te worden uitgevoerd.)
- Coderegel 4: Het overschrijft de run-methode van de uitvoerbare interface, omdat het verplicht is om die methode te overschrijven
- Coderegel 6: Hier hebben we de hoofdmethode gedefinieerd waarmee we de uitvoering van de thread zullen starten.
- Coderegel 7: Hier creëren we een nieuwe threadnaam als "guruthread1" door een nieuwe threadklasse te instantiëren.
- Coderegel 8: we zullen de “start” -methode van de thread gebruiken met behulp van de “guruthread1” -instantie. Hier wordt de thread uitgevoerd.
- Coderegel 10: Hier gebruiken we de “sleep” -methode van de thread met behulp van de instantie “guruthread1”. Daarom slaapt de draad gedurende 1000 milliseconden.
- Codering 9-14: Hier hebben we de slaapmethode in het try catch-blok geplaatst, omdat er een gecontroleerde uitzondering is die optreedt, dwz een onderbroken uitzondering.
- Coderegel 15: Hier stellen we de prioriteit van de thread in op 1, ongeacht de prioriteit die deze had
- Coderegel 16: Hier krijgen we de prioriteit van de thread met behulp van getPriority()
- Coderegel 17: Hier drukken we de waarde af die is opgehaald uit getPriority
- Coderegel 18: Hier schrijven we een tekst die in draad loopt.
Wanneer u de bovenstaande code uitvoert, krijgt u de volgende uitvoer:
Output:
5 is de Thread-prioriteit en Thread Running is de tekst die de uitvoer van onze code is.
Java Draad Synckroning
Bij multithreading is er sprake van asynchroon gedrag van de programma's. Als één thread gegevens schrijft en een andere thread tegelijkertijd gegevens leest, kan dit inconsistentie in de applicatie veroorzaken. Wanneer er behoefte is aan toegang tot de gedeelde bronnen door twee of meer threads, wordt de synchronisatiebenadering gebruikt. Java heeft gesynchroniseerde methoden geleverd om gesynchroniseerd gedrag te implementeren.
Bij deze aanpak kan geen enkele andere thread die methode op hetzelfde object aanroepen zodra de thread het gesynchroniseerde blok bereikt. Alle threads moeten wachten tot die thread het gesynchroniseerde blok heeft voltooid en eruit komt. Op deze manier helpt de synchronisatie in een multithreaded applicatie. Eén thread moet wachten tot een andere thread zijn uitvoering heeft voltooid, pas dan mogen de andere threads worden uitgevoerd.
Het kan in de volgende vorm worden geschreven:
Synchronized(object) { //Block of statements to be synchronized }
Multithreading-in Java Voorbeeldprogramma's
Bij deze multithreading Java We nemen bijvoorbeeld twee threads en halen de namen van de thread op.
Example1:
GuruThread1.java package demotest; public class GuruThread1 implements Runnable{ /** * @param args */ public static void main(String[] args) { Thread guruThread1 = new Thread("Guru1"); Thread guruThread2 = new Thread("Guru2"); guruThread1.start(); guruThread2.start(); System.out.println("Thread names are following:"); System.out.println(guruThread1.getName()); System.out.println(guruThread2.getName()); } @Override public void run() { } }
Uitleg van de code:
- Coderegel 3: We hebben een klasse “GuruThread1” genomen die Runnable implementeert (deze zou moeten worden geïmplementeerd door elke klasse waarvan de instanties bedoeld zijn om door de thread te worden uitgevoerd.)
- Coderegel 8: Dit is de belangrijkste methode van de klas
- Coderegel 9: Hier instantiëren we de Thread-klasse en maken we een instantie met de naam "guruThread1" en maken we een thread.
- Coderegel 10: Hier instantiëren we de Thread-klasse en maken we een instantie met de naam "guruThread2" en maken we een thread.
- Coderegel 11: We starten de draad, dat wil zeggen guruThread1.
- Coderegel 12: We starten de draad, dat wil zeggen guruThread2.
- Coderegel 13: De tekst weergeven als "Threadnamen volgen:"
- Coderegel 14: De naam van thread 1 ophalen met behulp van de methode getName() van de threadklasse.
- Coderegel 15: De naam van thread 2 ophalen met behulp van de methode getName() van de threadklasse.
Wanneer u de bovenstaande code uitvoert, krijgt u de volgende uitvoer:
Output:
Thread-namen worden hier uitgevoerd als
- Guru1
- Guru2
Voorbeeld 2:
Bij deze multithreading in Java We zullen bijvoorbeeld leren over het overschrijven van de methoden run() en start() van een uitvoerbare interface en twee threads van die klasse maken en deze dienovereenkomstig uitvoeren.
We volgen ook twee lessen,
- Eén die de uitvoerbare interface zal implementeren en
- Een andere die de hoofdmethode zal hebben en dienovereenkomstig zal worden uitgevoerd.
package demotest; public class GuruThread2 { public static void main(String[] args) { // TODO Auto-generated method stub GuruThread3 threadguru1 = new GuruThread3("guru1"); threadguru1.start(); GuruThread3 threadguru2 = new GuruThread3("guru2"); threadguru2.start(); } } class GuruThread3 implements Runnable { Thread guruthread; private String guruname; GuruThread3(String name) { guruname = name; } @Override public void run() { System.out.println("Thread running" + guruname); for (int i = 0; i < 4; i++) { System.out.println(i); System.out.println(guruname); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread has been interrupted"); } } } public void start() { System.out.println("Thread started"); if (guruthread == null) { guruthread = new Thread(this, guruname); guruthread.start(); } } }
Uitleg van de code:
- Coderegel 2: Hier nemen we een klasse “GuruThread2” die de hoofdmethode bevat.
- Coderegel 4: Hier nemen we een hoofdmethode van de klas.
- Coderegel 6-7: Hier maken we een instantie van klasse GuruThread3 (die in de onderstaande regels van de code is gemaakt) als "threadguru1" en starten we de thread.
- Coderegel 8-9: Hier maken we nog een exemplaar van de klasse GuruThread3 (die in de onderstaande regels van de code is gemaakt) als "threadguru2" en starten we de thread.
- Coderegel 11: Hier maken we een klasse “GuruThread3” die de uitvoerbare interface implementeert (deze moet worden geïmplementeerd door elke klasse waarvan de instanties bedoeld zijn om door de thread te worden uitgevoerd.)
- Coderegel 13-14: we nemen twee klassevariabelen waarvan er één van het type thread-klasse is en de andere van de string-klasse.
- Coderegel 15-18: we overschrijven de GuruThread3-constructor, die één argument als stringtype aanneemt (dat is de naam van de thread) die wordt toegewezen aan de klassevariabele guruname en daarom wordt de naam van de thread opgeslagen.
- Coderegel 20: Hier overschrijven we de run() -methode van de uitvoerbare interface.
- Coderegel 21: We voeren de threadnaam uit met behulp van de println-instructie.
- Coderegel 22-31: Hier gebruiken we een for-lus met de teller geïnitialiseerd op 0, en deze mag niet kleiner zijn dan 4 (we kunnen elk getal nemen, dus de lus wordt hier 4 keer uitgevoerd) en verhogen de teller. We drukken de threadnaam af en laten de thread ook gedurende 1000 milliseconden slapen binnen een try-catch-blok, terwijl de slaapmethode een gecontroleerde uitzondering opleverde.
- Coderegel 33: Hier overschrijven we de startmethode van de uitvoerbare interface.
- Coderegel 35: We geven de tekst 'Thread gestart' weer.
- Coderegel 36-40: Hier nemen we een if-voorwaarde om te controleren of de klassevariabele guruthread waarde bevat of niet. Als deze nul is, maken we een instantie met behulp van de threadklasse die de naam als parameter aanneemt (waarvoor de waarde is toegewezen in de constructor). Daarna wordt de thread gestart met behulp van de start()-methode.
Wanneer u de bovenstaande code uitvoert, krijgt u de volgende uitvoer:
uitgang:
Er zijn twee threads, dus we krijgen twee keer het bericht "Thread gestart".
We krijgen de namen van de thread zoals we ze hebben uitgevoerd.
Het gaat naar de for-lus waar we de teller en de draadnaam afdrukken en de teller begint met 0.
De lus wordt drie keer uitgevoerd en tussendoor wordt de draad 1000 milliseconden geslapen.
Daarom krijgen we eerst guru1, dan guru2 en dan weer guru2 omdat de thread hier 1000 milliseconden slaapt en dan de volgende guru1 en opnieuw guru1, de thread slaapt 1000 milliseconden, dus we krijgen guru2 en dan guru1.
Samenvatting
In deze tutorial zagen we multithreaded applicaties in Java en hoe je single- en multi-threads kunt gebruiken Java.
- Leg multithreading uit Java: bij multithreading worden gebruikers niet geblokkeerd omdat threads onafhankelijk zijn en meerdere bewerkingen tegelijk kunnen uitvoeren
- Verschillende stadia van de levenscyclus van de draad zijn,
- Nieuw
- uitvoerbare
- Hardlopen
- Het wachten
- Dood
- Wij hebben er ook over geleerd synchronisatie tussen threads, waardoor de applicatie soepel verloopt.
- Multithreaded programmeren in Java maakt nog veel meer toepassingstaken eenvoudiger.