Java - Multithreading
Java is een multi-threaded programmeertaal wat betekent dat we multi-threaded programma's kunnen ontwikkelen met behulp van Java. Een programma met meerdere threads bevat twee of meer delen die gelijktijdig kunnen worden uitgevoerd en elk deel kan tegelijkertijd een andere taak aan, waarbij optimaal gebruik wordt gemaakt van de beschikbare bronnen, vooral wanneer uw computer meerdere CPU's heeft.
Per definitie is multitasking wanneer meerdere processen gemeenschappelijke verwerkingsbronnen delen, zoals een CPU. Multi-threading breidt het idee van multitasking uit naar toepassingen waar u specifieke bewerkingen binnen een enkele toepassing kunt onderverdelen in afzonderlijke threads. Elk van de threads kan parallel lopen. Het besturingssysteem verdeelt de verwerkingstijd niet alleen over verschillende applicaties, maar ook over elke thread binnen een applicatie.
Multi-threading stelt u in staat om te schrijven op een manier waarbij meerdere activiteiten gelijktijdig in hetzelfde programma kunnen plaatsvinden.
Levenscyclus van een draad
Een draad doorloopt verschillende stadia in zijn levenscyclus. Een draad wordt bijvoorbeeld geboren, gestart, loopt en sterft dan. Het volgende diagram toont de volledige levenscyclus van een thread.
Hieronder volgen de fasen van de levenscyclus −
-
Nieuw − Een nieuwe draad begint zijn levenscyclus in de nieuwe staat. Het blijft in deze staat totdat het programma de thread start. Er wordt ook naar verwezen als een geboren draad .
-
Uitvoerbaar − Nadat een nieuw geboren draad is gestart, wordt de draad berijdbaar. Een thread in deze staat wordt geacht zijn taak uit te voeren.
-
Wachten − Soms gaat een thread over naar de wachtstatus terwijl de thread wacht op een andere thread om een taak uit te voeren. Een thread gaat alleen terug naar de uitvoerbare status wanneer een andere thread de wachtende thread signaleert om door te gaan met uitvoeren.
-
Getimed wachten − Een uitvoerbare thread kan gedurende een gespecificeerd tijdsinterval de getimede wachtstatus binnengaan. Een thread in deze status gaat terug naar de uitvoerbare status wanneer dat tijdsinterval verstrijkt of wanneer de gebeurtenis waarop wordt gewacht plaatsvindt.
-
Beëindigd (dood) − Een uitvoerbare thread gaat naar de beëindigde status wanneer deze zijn taak voltooit of anderszins wordt beëindigd.
Draadprioriteiten
Elke Java-thread heeft een prioriteit die het besturingssysteem helpt bij het bepalen van de volgorde waarin threads zijn gepland.
De prioriteiten van Java-threads liggen in het bereik tussen MIN_PRIORITY (een constante van 1) en MAX_PRIORITY (een constante van 10). Standaard krijgt elke thread prioriteit NORM_PRIORITY (een constante van 5).
Threads met een hogere prioriteit zijn belangrijker voor een programma en moeten processortijd krijgen voor threads met een lagere prioriteit. Threadprioriteiten kunnen echter de volgorde waarin threads worden uitgevoerd niet garanderen en zijn erg platformafhankelijk.
Maak een thread door een uitvoerbare interface te implementeren
Als uw klasse bedoeld is om als een thread te worden uitgevoerd, kunt u dit bereiken door een Uitvoerbaar te implementeren koppel. U moet drie basisstappen volgen −
Stap 1
Als eerste stap moet u een methode run() implementeren die wordt geleverd door een Uitvoerbaar koppel. Deze methode biedt een toegangspunt voor de thread en u plaatst uw volledige bedrijfslogica in deze methode. Hieronder volgt een eenvoudige syntaxis van de methode run() −
public void run( )
Stap 2
Als tweede stap start je een Thread object met de volgende constructor −
Thread(Runnable threadObj, String threadName);
Waar, threadObj is een instantie van een klasse die de Uitvoerbare . implementeert interface en threadName is de naam die aan de nieuwe thread wordt gegeven.
Stap 3
Zodra een Thread-object is gemaakt, kunt u het starten door start() . aan te roepen methode, die een aanroep naar de methode run() uitvoert. Hieronder volgt een eenvoudige syntaxis van de start()-methode −
void start();
Voorbeeld
Hier is een voorbeeld dat een nieuwe thread aanmaakt en begint te draaien −
Live democlass RunnableDemo implements Runnable { private Thread t; private String threadName; RunnableDemo( String name) { threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + ", " + i); // Let the thread sleep for a while. Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { RunnableDemo R1 = new RunnableDemo( "Thread-1"); R1.start(); RunnableDemo R2 = new RunnableDemo( "Thread-2"); R2.start(); } }
Dit levert het volgende resultaat op −
Uitvoer
Creating Thread-1 Starting Thread-1 Creating Thread-2 Starting Thread-2 Running Thread-1 Thread: Thread-1, 4 Running Thread-2 Thread: Thread-2, 4 Thread: Thread-1, 3 Thread: Thread-2, 3 Thread: Thread-1, 2 Thread: Thread-2, 2 Thread: Thread-1, 1 Thread: Thread-2, 1 Thread Thread-1 exiting. Thread Thread-2 exiting.
Maak een thread door een threadklasse uit te breiden
De tweede manier om een thread aan te maken is door een nieuwe klasse aan te maken die Thread uitbreidt klasse met behulp van de volgende twee eenvoudige stappen. Deze aanpak biedt meer flexibiliteit bij het afhandelen van meerdere threads die zijn gemaakt met behulp van beschikbare methoden in de Thread-klasse.
Stap 1
U moet run( ) . overschrijven methode beschikbaar in de klasse Thread. Deze methode biedt een toegangspunt voor de thread en u plaatst uw volledige bedrijfslogica in deze methode. Hieronder volgt een eenvoudige syntaxis van de methode run() −
public void run( )
Stap 2
Nadat het Thread-object is gemaakt, kunt u het starten door start() . aan te roepen methode, die een aanroep naar de methode run() uitvoert. Hieronder volgt een eenvoudige syntaxis van de start()-methode −
void start( );
Voorbeeld
Hier is het voorgaande programma herschreven om de Thread uit te breiden −
Live democlass ThreadDemo extends Thread { private Thread t; private String threadName; ThreadDemo( String name) { threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + ", " + i); // Let the thread sleep for a while. Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { ThreadDemo T1 = new ThreadDemo( "Thread-1"); T1.start(); ThreadDemo T2 = new ThreadDemo( "Thread-2"); T2.start(); } }
Dit levert het volgende resultaat op −
Uitvoer
Creating Thread-1 Starting Thread-1 Creating Thread-2 Starting Thread-2 Running Thread-1 Thread: Thread-1, 4 Running Thread-2 Thread: Thread-2, 4 Thread: Thread-1, 3 Thread: Thread-2, 3 Thread: Thread-1, 2 Thread: Thread-2, 2 Thread: Thread-1, 1 Thread: Thread-2, 1 Thread Thread-1 exiting. Thread Thread-2 exiting.
Draadmethoden
Hieronder volgt de lijst met belangrijke methoden die beschikbaar zijn in de Thread-klasse.
Zr.nr. | Methode en beschrijving |
---|---|
1 | public void start() Start de thread in een apart uitvoeringspad en roept vervolgens de methode run() op voor dit Thread-object. |
2 | public void run() Als dit Thread-object is geïnstantieerd met een afzonderlijk Runnable-doel, wordt de methode run() aangeroepen op dat Runnable-object. |
3 | public final void setName(String name) Wijzigt de naam van het Thread-object. Er is ook een methode getName() om de naam op te halen. |
4 | public final void setPriority(int priority) Stelt de prioriteit van dit Thread-object in. De mogelijke waarden liggen tussen 1 en 10. |
5 | public final void setDaemon(boolean on) Een parameter van true geeft deze thread aan als een daemon-thread. |
6 | public final void join(lange millisec) De huidige thread roept deze methode aan op een tweede thread, waardoor de huidige thread wordt geblokkeerd totdat de tweede thread eindigt of het opgegeven aantal milliseconden verstrijkt. |
7 | public void interrupt() Onderbreekt deze thread, waardoor de uitvoering wordt voortgezet als deze om welke reden dan ook werd geblokkeerd. |
8 | openbare finale boolean isAlive() Retourneert true als de thread in leven is, wat op elk moment is nadat de thread is gestart, maar voordat deze is voltooid. |
De vorige methoden worden aangeroepen voor een bepaald Thread-object. De volgende methoden in de klasse Thread zijn statisch. Het aanroepen van een van de statische methoden voert de bewerking uit op de huidige thread.
Zr.nr. | Methode en beschrijving |
---|---|
1 | publieke statische leegte opbrengst() Zorgt ervoor dat de momenteel lopende thread bezwijkt voor andere threads met dezelfde prioriteit die wachten om te worden gepland. |
2 | openbare statische slaapstand (lange millisec) Zorgt ervoor dat de huidige thread minimaal het opgegeven aantal milliseconden blokkeert. |
3 | public static boolean holdLock(Object x) Retourneert waar als de huidige thread het slot op het gegeven object bevat. |
4 | openbare statische Thread currentThread() Retourneert een verwijzing naar de huidige thread, de thread die deze methode aanroept. |
5 | openbare statische leegte dumpStack() Drukt de stacktracering af voor de momenteel actieve thread, wat handig is bij het debuggen van een toepassing met meerdere threads. |
Voorbeeld
Het volgende ThreadClassDemo-programma demonstreert enkele van deze methoden van de klasse Thread. Overweeg een klas DisplayMessage die Uitvoerbaar . implementeert
// File Name : DisplayMessage.java // Create a thread to implement Runnable public class DisplayMessage implements Runnable { private String message; public DisplayMessage(String message) { this.message = message; } public void run() { while(true) { System.out.println(message); } } }
Hierna volgt een andere klasse die de Thread-klasse uitbreidt −
// File Name : GuessANumber.java // Create a thread to extentd Thread public class GuessANumber extends Thread { private int number; public GuessANumber(int number) { this.number = number; } public void run() { int counter = 0; int guess = 0; do { guess = (int) (Math.random() * 100 + 1); System.out.println(this.getName() + " guesses " + guess); counter++; } while(guess != number); System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**"); } }
Hieronder volgt het hoofdprogramma, dat gebruik maakt van de hierboven gedefinieerde klassen −
// File Name : ThreadClassDemo.java public class ThreadClassDemo { public static void main(String [] args) { Runnable hello = new DisplayMessage("Hello"); Thread thread1 = new Thread(hello); thread1.setDaemon(true); thread1.setName("hello"); System.out.println("Starting hello thread..."); thread1.start(); Runnable bye = new DisplayMessage("Goodbye"); Thread thread2 = new Thread(bye); thread2.setPriority(Thread.MIN_PRIORITY); thread2.setDaemon(true); System.out.println("Starting goodbye thread..."); thread2.start(); System.out.println("Starting thread3..."); Thread thread3 = new GuessANumber(27); thread3.start(); try { thread3.join(); } catch (InterruptedException e) { System.out.println("Thread interrupted."); } System.out.println("Starting thread4..."); Thread thread4 = new GuessANumber(75); thread4.start(); System.out.println("main() is ending..."); } }
Dit levert het volgende resultaat op. Je kunt dit voorbeeld keer op keer proberen en je krijgt elke keer een ander resultaat.
Uitvoer
Starting hello thread... Starting goodbye thread... Hello Hello Hello Hello Hello Hello Goodbye Goodbye Goodbye Goodbye Goodbye .......
Belangrijke Java Multithreading Concepten
Terwijl u Multithreading programmeert in Java, moet u de volgende concepten erg handig hebben −
-
Wat is threadsynchronisatie?
-
Interthread-communicatie afhandelen
-
Omgaan met een vastgelopen draad
-
Grote threadbewerkingen
Java