Elke applicatie kan meerdere processen (instanties) hebben. Elk van deze processen kan worden toegewezen als een enkele thread of meerdere threads. We zullen in deze tutorial zien hoe je meerdere taken tegelijkertijd kunt uitvoeren en ook meer leren over threads en synchronisatie tussen threads.
In deze tutorial leren we:
- Wat is enkele draad
- Wat is multithreading in Java?
- Thread Life Cycle in Java
- Synchronisatie van Java-discussies
- Voorbeeld van multithreading in Java
Wat is een enkele draad?
Een enkele draad is in feite een lichtgewicht en de kleinste verwerkingseenheid. Java gebruikt threads door een "Thread Class" te gebruiken.
Er zijn twee soorten thread - gebruikersthread en daemon-thread (daemon-threads worden gebruikt als we de applicatie willen opschonen en worden op de achtergrond gebruikt).
Wanneer een toepassing voor het eerst start, wordt een gebruikersthread gemaakt. Post dat, we kunnen veel gebruikersthreads en daemon-threads maken.
Enkele draad voorbeeld:
pakket demotest;openbare klasse GuruThreadpublic static void main (String [] args) {System.out.println ("Single Thread");
Voordelen van enkele draad:
- Vermindert overhead in de applicatie als enkele thread wordt uitgevoerd in het systeem
- Het verlaagt ook de onderhoudskosten van de applicatie.
Wat is multithreading in Java?
MULTITHREADING in Java is een proces waarbij twee of meer threads tegelijkertijd worden uitgevoerd om de CPU maximaal te gebruiken. Multithreaded applicaties voeren twee of meer threads tegelijk uit. Daarom is het ook bekend als Concurrency in Java. Elke draad loopt parallel aan elkaar. Meerdere threads wijzen geen apart geheugengebied toe, waardoor ze geheugen besparen. Bovendien kost het wisselen van context tussen threads minder tijd.
Voorbeeld van multi-thread:
pakket demotest;openbare klasse GuruThread1 implementeert Runnablepublic static void main (String [] args) {Thread guruThread1 = nieuwe Thread ("Guru1");Thread guruThread2 = nieuwe Thread ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Threadnamen volgen:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());@Overrideopenbare ongeldige run () {
Voordelen van multithread:
- De gebruikers worden niet geblokkeerd omdat threads onafhankelijk zijn en we soms meerdere bewerkingen kunnen uitvoeren
- Als zodanig zijn de threads onafhankelijk, de andere threads worden niet beïnvloed als een thread aan een uitzondering voldoet.
Thread Life Cycle in Java
De levenscyclus van een thread:
Er zijn verschillende stadia van de levenscyclus van draad, zoals weergegeven in het bovenstaande diagram:
- Nieuw
- Runnable
- Rennen
- Aan het wachten
- Dood
- Nieuw: in deze fase wordt de thread gemaakt met de klasse "Thread class". Het blijft in deze staat totdat het programma de thread start . Het is ook bekend als geboren draad.
- Runnable: op deze pagina wordt de instantie 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 begint met uitvoeren, wordt de status gewijzigd in de status "running". De planner selecteert een thread uit de threadpool en deze wordt in de applicatie uitgevoerd.
- Wachten: dit is de toestand waarin een thread moet wachten. Aangezien er meerdere threads worden uitgevoerd in de applicatie, is er behoefte aan synchronisatie tussen threads. Daarom moet de ene thread wachten totdat de andere thread wordt uitgevoerd. Daarom wordt deze toestand de wachttoestand genoemd.
- Dead: dit is de status waarin de thread wordt beëindigd. De thread is in actieve toestand en zodra de verwerking is voltooid, bevindt deze zich in "dode toestand".
Enkele van de meest gebruikte methoden voor threads zijn:
Methode | Omschrijving |
---|---|
begin() | Deze methode start de uitvoering van de thread en JVM roept de methode run () op de thread aan. |
Slaap (int milliseconden) | Deze methode zorgt ervoor dat de thread slaapt, vandaar dat de uitvoering van de thread gedurende milliseconden zal pauzeren en daarna opnieuw begint de thread met uitvoeren. Dit helpt bij het synchroniseren van de threads. |
getName () | Het retourneert de naam van de thread. |
setPriority (int newpriority) | Het verandert de prioriteit van de thread. |
opbrengst () | Het zorgt ervoor dat de huidige thread stilstaat en andere threads worden uitgevoerd. |
Voorbeeld: in dit voorbeeld gaan we een thread maken en de ingebouwde methoden verkennen die beschikbaar zijn voor threads.
pakket demotest;openbare klasse thread_example1 implementeert Runnable {@Overrideopenbare ongeldige run () {public static void main (String [] args) {Thread guruthread1 = nieuwe Thread ();guruthread1.start ();proberen {guruthread1.sleep (1000);} catch (InterruptedException e) {// TODO Automatisch gegenereerd catch-bloke.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 belangrijkste methode gedefinieerd waarmee we de uitvoering van de thread zullen starten.
- Coderegel 7: Hier maken we een nieuwe threadnaam aan 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 "slaap" -methode van de thread met behulp van de "guruthread1" -instantie. Daarom zal de draad 1000 milliseconden slapen.
- Code 9-14: Hier hebben we de slaapmethode in het try catch-blok gezet 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
- 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 thread wordt uitgevoerd.
Als je de bovenstaande code uitvoert, krijg je de volgende output:
Uitgang:
5 is de Thread-prioriteit en Thread Running is de tekst die de uitvoer is van onze code.
Synchronisatie van Java-discussies
Bij multithreading is er het asynchrone gedrag van de programma's. Als een thread gegevens schrijft en een andere thread die tegelijkertijd gegevens leest, kan dit leiden tot inconsistentie in de toepassing.
Wanneer er behoefte is om toegang te krijgen tot de gedeelde bronnen via twee of meer threads, wordt de synchronisatiebenadering gebruikt.
Java heeft gesynchroniseerde methoden geleverd om gesynchroniseerd gedrag te implementeren.
In deze benadering, zodra de thread het gesynchroniseerde blok bereikt, kan geen enkele andere thread die methode op hetzelfde object aanroepen. Alle threads moeten wachten tot die thread het gesynchroniseerde blok heeft voltooid en daaruit komt.
Op deze manier helpt de synchronisatie bij een multithread-applicatie. De ene thread moet wachten tot de andere thread de uitvoering heeft voltooid, alleen dan mogen de andere threads worden uitgevoerd.
Het kan in de volgende vorm worden geschreven:
Gesynchroniseerd (object)// Blok met te synchroniseren instructies
Voorbeeld van multithreading in Java
In dit voorbeeld nemen we twee threads en halen de namen van de thread op.
Voorbeeld 1:
GuruThread1.javapakket demotest;openbare klasse GuruThread1 implementeert Runnable {* @param argspublic static void main (String [] args) {Thread guruThread1 = nieuwe Thread ("Guru1");Thread guruThread2 = nieuwe Thread ("Guru2");guruThread1.start ();guruThread2.start ();System.out.println ("Threadnamen volgen:");System.out.println (guruThread1.getName ());System.out.println (guruThread2.getName ());@Overrideopenbare ongeldige run () {
Uitleg van de code:
- Coderegel 3: We hebben een klasse "GuruThread1" genomen die Runnable implementeert (het moet 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 klasse Thread en maken we een instantie met de naam "guruThread2" en maken we een thread.
- Coderegel 11: We beginnen de thread, dwz guruThread1.
- Coderegel 12: We beginnen de thread, dwz guruThread2.
- Coderegel 13: het uitvoeren van de tekst als "Discussienamen volgen:"
- Coderegel 14: de naam van thread 1 ophalen met de methode getName () van de threadklasse.
- Coderegel 15: de naam van thread 2 ophalen met de methode getName () van de threadklasse.
Als je de bovenstaande code uitvoert, krijg je de volgende output:
Uitgang:
Thread-namen worden hier uitgevoerd als
- Goeroe 1
- Guru 2
Voorbeeld 2:
In dit voorbeeld zullen we leren over het overschrijven van methoden run () en start () methode van een uitvoerbare interface en twee threads van die klasse maken en ze dienovereenkomstig uitvoeren.
We volgen ook twee lessen,
- Een die de uitvoerbare interface zal implementeren en
- Een andere die de hoofdmethode heeft en dienovereenkomstig wordt uitgevoerd.
pakket demotest;openbare klasse GuruThread2 {public static void main (String [] args) {// TODO Automatisch gegenereerde methodestubGuruThread3 threadguru1 = nieuwe GuruThread3 ("guru1");threadguru1.start ();GuruThread3 threadguru2 = nieuwe GuruThread3 ("guru2");threadguru2.start ();class GuruThread3 implementeert Runnable {Draad guruthread;private String guruname;GuruThread3 (String naam) {guruname = naam;@Overrideopenbare ongeldige run () {System.out.println ("Thread loopt" + guruname);voor (int i = 0; i <4; i ++) {System.out.println (i);System.out.println (guruname);proberen {Thread.sleep (1000);} catch (InterruptedException e) {System.out.println ("Thread is onderbroken");openbare ongeldige start () {System.out.println ("Thread gestart");if (guruthread == null) {guruthread = nieuwe thread (dit, guruname);guruthread.start ();
Uitleg van de code:
- Coderegel 2: Hier nemen we een klasse "GuruThread2" die de hoofdmethode erin zal hebben.
- Coderegel 4: Hier nemen we een hoofdmethode van de klas.
- Coderegel 6-7: Hier maken we een instantie van klasse GuruThread3 (die wordt gemaakt in onderstaande regels van de code) als "threadguru1" en we beginnen de thread.
- Coderegel 8-9: Hier maken we nog een instantie van klasse GuruThread3 (die wordt gemaakt in onderstaande regels van de code) als "threadguru2" en we beginnen 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 de ene van het type threadklasse is en de andere van de stringklasse.
- Coderegel 15-18: we overschrijven de constructor GuruThread3, die één argument als stringtype gebruikt (dit is de naam van de thread) dat wordt toegewezen aan de klassevariabele guruname en daarom wordt de naam van de thread opgeslagen.
- Coderegel 20: hier overschrijven we de methode run () van de uitvoerbare interface.
- Coderegel 21: We voeren de threadnaam uit met behulp van de instructie println.
- Coderegel 22-31: hier gebruiken we een for-lus met een teller die is geïnitialiseerd op 0, en deze mag niet minder zijn dan 4 (we kunnen elk getal nemen, dus de lus wordt hier 4 keer uitgevoerd) en de teller wordt verhoogd. We drukken de threadnaam af en laten de thread ook 1000 milliseconden slapen binnen een try-catch-blok als slaapmethode verhoogde gecontroleerde uitzondering.
- Coderegel 33: Hier overschrijven we de startmethode van de uitvoerbare interface.
- Coderegel 35: We voeren de tekst "Thread gestart" uit.
- Coderegel 36-40: Hier nemen we een if-voorwaarde om te controleren of de klassevariabele guruthread waarde bevat of niet. Als het null is, maken we een instantie met behulp van de thread-klasse die de naam als parameter gebruikt (waarde waarvoor is toegewezen in de constructor). Waarna de thread wordt gestart met de methode start ().
Als je de bovenstaande code uitvoert, krijg je de volgende output:
Uitgang :
Er zijn twee threads, dus we krijgen twee keer de melding "Thread gestart".
We krijgen de namen van de thread zoals we ze hebben uitgevoerd.
Het gaat in de for-lus waar we de teller en de draadnaam afdrukken en de teller begint met 0.
De lus wordt drie keer uitgevoerd en daartussen 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 vervolgens guru1 en opnieuw guru1, thread slaapt 1000 milliseconden, dus we krijgen guru2 en dan guru1.
Samenvatting :
In deze zelfstudie hebben we toepassingen met meerdere threads in Java gezien en hoe u enkele en meerdere threads kunt gebruiken.
- 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
- Runnable
- Rennen
- Aan het wachten
- Dood
- We leerden ook over synchronisatie tussen threads, waardoor de applicatie soepel verloopt.
- Multithreading maakt veel meer applicatietaken eenvoudiger.