Multithreading in Java


Jede Anwendung kann mehrere Prozesse (Instanzen) haben. Jeder dieser Prozesse kann entweder als einzelner Thread oder als mehrere Threads zugewiesen werden. In diesem Tutorial erfahren Sie, wie Sie mehrere Aufgaben gleichzeitig ausführen und erfahren mehr über Threads und die Synchronisierung zwischen Threads.

Was ist Single-Thread?

Ein einzelner Thread in Java ist im Grunde genommen ein Leichtgewicht und die kleinste Verarbeitungseinheit. Java verwendet Threads mithilfe einer „Thread-Klasse“. Es gibt zwei Arten von Threads – Benutzer-Thread und Daemon-Thread (Daemon-Threads werden verwendet, wenn wir die Anwendung bereinigen möchten und werden im Hintergrund verwendet). Wenn eine Anwendung zum ersten Mal gestartet wird, wird ein Benutzer-Thread erstellt. Danach können wir viele Benutzer-Threads und Daemon-Threads erstellen.

Beispiel für einen einzelnen Thread:

package demotest;

public class GuruThread
{
       public static void main(String[] args) {
              System.out.println("Single Thread");
       }
}

Vorteile von Single-Thread:

  • Reduziert den Overhead in der Anwendung, da ein einzelner Thread im System ausgeführt wird
  • Außerdem werden die Wartungskosten der Anwendung reduziert.

Was ist Multithreading in Java?

Multithreading in Java ist ein Prozess, bei dem zwei oder mehr Threads gleichzeitig ausgeführt werden, um die CPU maximal auszulasten. Multithread-Anwendungen führen zwei oder mehr Threads gleichzeitig aus. Daher wird es auch als Parallelität bezeichnet in Java. Jeder Thread läuft parallel zu den anderen. Mehrere Threads belegen keinen separaten Speicherbereich und sparen daher Speicher. Außerdem dauert der Kontextwechsel zwischen Threads weniger Zeit.

Beispiel für Multithread:

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() {
    }
}

Vorteile von Multithread:

  • Die Benutzer werden nicht blockiert, da die Threads unabhängig sind und wir mehrere Vorgänge gleichzeitig ausführen können.
  • Da die Threads unabhängig sind, sind die anderen Threads nicht betroffen, wenn ein Thread auf eine Ausnahme trifft.

Thread-Lebenszyklus in Java

Der Lebenszyklus eines Threads:

Thread-Lebenszyklus in Java
Thread-Lebenszyklus in Java

Es gibt verschiedene Phasen im Lebenszyklus eines Threads, wie im obigen Diagramm dargestellt:

  1. New
  2. Lauffähig
  3. Laufen
  4. Warten
  5. Dead
  1. Neu: In dieser Phase wird der Thread mithilfe der Klasse „Thread-Klasse“ erstellt. Er bleibt in diesem Zustand, bis das Programm ausgeführt wird beginnt der Faden. Es ist auch als Born Thread bekannt.
  2. Lauffähig: Auf dieser Seite wird die Instanz des Threads mit einer Startmethode aufgerufen. Die Thread-Steuerung wird dem Scheduler übergeben, um die Ausführung abzuschließen. Es hängt vom Scheduler ab, ob der Thread ausgeführt werden soll.
  3. Laufen: Wenn die Ausführung des Threads beginnt, ändert sich der Status in den Status „Wird ausgeführt“. Der Scheduler wählt einen Thread aus dem Thread-Pool aus und beginnt mit der Ausführung in der Anwendung.
  4. Warten: Dies ist der Zustand, in dem ein Thread warten muss. Da in der Anwendung mehrere Threads ausgeführt werden, ist eine Synchronisierung zwischen den Threads erforderlich. Daher muss ein Thread warten, bis der andere Thread ausgeführt wird. Daher wird dieser Zustand als Wartezustand bezeichnet.
  5. Tot: Dies ist der Zustand, wenn der Thread beendet wird. Der Thread befindet sich im laufenden Zustand und befindet sich, sobald er die Verarbeitung abgeschlossen hat, im „toten Zustand“.


Methoden des Multithreading in Java

Einige der häufig verwendeten Methoden für Threads sind:

Methodik Beschreibung
Start() Diese Methode startet die Ausführung des Threads und JVM ruft die run()-Methode für den Thread auf.
Schlaf (int Millisekunden) Diese Methode versetzt den Thread in den Ruhezustand, sodass die Ausführung des Threads für die angegebenen Millisekunden angehalten wird und danach erneut mit der Ausführung des Threads begonnen wird. Dies hilft bei der Synchronisierung der Threads.
getName () Es gibt den Namen des Threads zurück.
setPriority(int newpriority) Es ändert die Priorität des Threads.
Ertrag () Dadurch wird der aktuelle Thread angehalten und andere Threads ausgeführt.

Ejemplo: In diesem Multithreading-Programm in Java Beispiel: Wir werden einen Thread erstellen und die für Threads verfügbaren integrierten Methoden untersuchen.

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");
  }
}

Erklärung des Codes:

  • Code Linie 2: Wir erstellen eine Klasse „thread_Example1“, die die Runnable-Schnittstelle implementiert (sie sollte von jeder Klasse implementiert werden, deren Instanzen vom Thread ausgeführt werden sollen).
  • Code Linie 4: Es überschreibt die Ausführungsmethode der ausführbaren Schnittstelle, da diese Methode unbedingt überschrieben werden muss
  • Code Linie 6: Hier haben wir die Hauptmethode definiert, mit der wir die Ausführung des Threads starten.
  • Code Linie 7: Hier erstellen wir einen neuen Thread-Namen als „guruthread1“, indem wir eine neue Thread-Klasse instanziieren.
  • Code Linie 8: Wir werden die „Start“-Methode des Threads mit der Instanz „guruthread1“ verwenden. Hier beginnt die Ausführung des Threads.
  • Code Linie 10: Hier verwenden wir die „sleep“-Methode des Threads mit der Instanz „guruthread1“. Daher schläft der Thread 1000 Millisekunden lang.
  • Code 9-14: Hier haben wir die Sleep-Methode in den Try-Catch-Block eingefügt, da dort eine überprüfte Ausnahme auftritt, dh eine unterbrochene Ausnahme.
  • Code Linie 15: Hier setzen wir die Priorität des Threads auf 1, unabhängig von der Priorität, die er hatte
  • Code Linie 16: Hier erhalten wir die Priorität des Threads mit getPriority()
  • Code Linie 17: Hier drucken wir den von getPriority abgerufenen Wert
  • Code Linie 18: Hier schreiben wir einen Text, in dem der Thread läuft.

Wenn Sie den obigen Code ausführen, erhalten Sie die folgende Ausgabe:

Thread-Beispiel in Java

Ausgang:

5 ist die Thread-Priorität und Thread Running ist der Text, der die Ausgabe unseres Codes darstellt.

Java Thread SyncHronisierung

Beim Multithreading kommt es zu einem asynchronen Verhalten der Programme. Wenn ein Thread Daten schreibt und ein anderer Thread gleichzeitig Daten liest, kann dies zu Inkonsistenzen in der Anwendung führen. Wenn zwei oder mehr Threads auf die gemeinsam genutzten Ressourcen zugreifen müssen, wird ein Synchronisierungsansatz verwendet. Java hat synchronisierte Methoden zur Implementierung synchronisierten Verhaltens bereitgestellt.

Bei diesem Ansatz kann kein anderer Thread diese Methode für dasselbe Objekt aufrufen, sobald der Thread den synchronisierten Block erreicht hat. Alle Threads müssen warten, bis dieser Thread den synchronisierten Block beendet und ihn verlässt. Auf diese Weise hilft die Synchronisierung bei einer Multithread-Anwendung. Ein Thread muss warten, bis der andere Thread seine Ausführung beendet hat, erst dann dürfen die anderen Threads ausgeführt werden.

Es kann in der folgenden Form geschrieben werden:

Synchronized(object)
{  
        //Block of statements to be synchronized
}

Multithreading in Java Beispielprogramme

In diesem Multithreading Java Beispiel: Wir nehmen zwei Threads und holen die Namen der Threads.

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() {
    }
}

Erklärung des Codes:

  • Code Linie 3: Wir haben einen Kurs belegt.GuruThread1“ implementiert Runnable (dies sollte von jeder Klasse implementiert werden, deren Instanzen vom Thread ausgeführt werden sollen).
  • Code Linie 8: Dies ist die Hauptmethode der Klasse
  • Code Linie 9: Hier instanziieren wir die Thread-Klasse, erstellen eine Instanz mit dem Namen „guruThread1“ und erstellen einen Thread.
  • Code Linie 10: Hier instanziieren wir die Thread-Klasse, erstellen eine Instanz mit dem Namen „guruThread2“ und erstellen einen Thread.
  • Code Linie 11: Wir starten den Thread, dh guruThread1.
  • Code Linie 12: Wir starten den Thread, dh guruThread2.
  • Code Linie 13: Ausgabe des Textes als „Die Threadnamen lauten wie folgt:“
  • Code Linie 14: Den Namen von Thread 1 mithilfe der Methode getName() der Thread-Klasse ermitteln.
  • Code Linie 15: Den Namen von Thread 2 mithilfe der Methode getName() der Thread-Klasse ermitteln.

Wenn Sie den obigen Code ausführen, erhalten Sie die folgende Ausgabe:

Java Multithreading-Beispiel

Ausgang:

Thread-Namen werden hier ausgegeben als

  • Guru1
  • Guru2

Beispiel 2:

In diesem Multithreading in Java Beispiel: Wir lernen, wie man die Methoden run() und start() einer ausführbaren Schnittstelle überschreibt und zwei Threads dieser Klasse erstellt und sie entsprechend ausführt.

Außerdem nehmen wir an zwei Kursen teil,

  • Eines, das die ausführbare Schnittstelle implementiert und
  • Eine andere, die die Hauptmethode hat und entsprechend ausgeführt wird.
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();
  }
 }
}

Erklärung des Codes:

  • Code Linie 2: Hier nehmen wir an einem Kurs teil.GuruThread2“, der die Hauptmethode enthält.
  • Code Linie 4: Hier nehmen wir eine Hauptmethode der Klasse.
  • Code Zeile 6-7: Hier erstellen wir eine Instanz der Klasse GuruThread3 (der in den folgenden Codezeilen erstellt wird) heißt „threadguru1“ und wir starten den Thread.
  • Code Zeile 8-9: Hier erstellen wir eine weitere Instanz der Klasse GuruThread3 (der in den folgenden Codezeilen erstellt wird) heißt „threadguru2“ und wir starten den Thread.
  • Code Linie 11: Hier erstellen wir eine Klasse „GuruThread3“ implementiert das Runnable-Interface (es sollte von jeder Klasse implementiert werden, deren Instanzen vom Thread ausgeführt werden sollen).
  • Code Zeile 13-14: Wir nehmen zwei Klassenvariablen, von denen eine vom Typ Thread-Klasse und die andere vom Typ String-Klasse ist.
  • Code Zeile 15-18: Wir setzen die GuruDer Thread3-Konstruktor nimmt ein Argument vom Typ String entgegen (den Namen des Threads), das der Klassenvariablen guruname zugewiesen wird, wodurch der Name des Threads gespeichert wird.
  • Code Linie 20: Hier überschreiben wir die run()-Methode der ausführbaren Schnittstelle.
  • Code Linie 21: Wir geben den Thread-Namen mit der println-Anweisung aus.
  • Code Zeile 22-31: Hier verwenden wir eine for-Schleife mit einem auf 0 initialisierten Zähler, der nicht kleiner als 4 sein sollte (wir können jede beliebige Zahl annehmen, daher wird die Schleife hier viermal ausgeführt) und erhöhen den Zähler. Wir geben den Thread-Namen aus und sorgen dafür, dass der Thread innerhalb eines Try-Catch-Blocks 4 Millisekunden lang in den Ruhezustand versetzt wird, da die Sleep-Methode eine geprüfte Ausnahme auslöst.
  • Code Linie 33: Hier überschreiben wir die Startmethode der ausführbaren Schnittstelle.
  • Code Linie 35: Wir geben den Text „Thread gestartet“ aus.
  • Code Zeile 36-40: Hier verwenden wir eine if-Bedingung, um zu prüfen, ob die Klassenvariable guruthread einen Wert enthält oder nicht. Wenn es null ist, erstellen wir eine Instanz mithilfe der Thread-Klasse, die den Namen als Parameter verwendet (der Wert wurde im Konstruktor zugewiesen). Danach wird der Thread mit der Methode start() gestartet.

Wenn Sie den obigen Code ausführen, erhalten Sie die folgende Ausgabe:

Multithreading-Beispiel in Java

Ausgang:

Da es zwei Threads gibt, erhalten wir zweimal die Meldung „Thread gestartet“.

Wir erhalten die Namen der Threads so, wie wir sie ausgegeben haben.

Es geht in die for-Schleife, in der wir den Zähler und den Thread-Namen drucken und der Zähler mit 0 beginnt.

Die Schleife wird dreimal ausgeführt und dazwischen ruht der Thread für 1000 Millisekunden.

Daher erhalten wir zuerst Guru1, dann Guru2 und dann noch einmal Guru2, weil der Thread hier 1000 Millisekunden lang schläft, und dann folgt Guru1 und wieder Guru1, der Thread schläft 1000 Millisekunden lang, also erhalten wir Guru2 und dann Guru1.

Zusammenfassung

In diesem Tutorial haben wir Multithread-Anwendungen gesehen in Java und wie man Single- und Multi-Thread verwendet in Java.

  • Erklären Sie Multithreading in Java: Beim Multithreading werden Benutzer nicht blockiert, da Threads unabhängig sind und mehrere Vorgänge gleichzeitig ausführen können
  • Verschiedene Phasen des Lebenszyklus des Threads sind:
    • New
    • Lauffähig
    • Laufen
    • Warten
    • Dead
  • Wir haben auch davon erfahren Synchronisation zwischen Threads, die dazu beitragen, dass die Anwendung reibungslos läuft.
  • Multithread-Programmierung in Java erleichtert viele weitere Anwendungsaufgaben.

Fassen Sie diesen Beitrag mit folgenden Worten zusammen: