JavaRush /Java-Blog /Random-DE /Zeit mit Streams genießen
Andrei
Level 2

Zeit mit Streams genießen

Veröffentlicht in der Gruppe Random-DE

Vorwort. Onkel Petja

Nehmen wir also an, wir wollten eine Flasche Wasser füllen. Eine Flasche und Leitungswasser von Onkel Petja stehen zur Verfügung. Onkel Petja ließ heute einen neuen Wasserhahn installieren und lobte immer wieder seine Schönheit. Davor benutzte er nur einen alten, verstopften Zapfhahn, sodass die Warteschlangen bei der Abfüllung riesig waren. Nachdem ich ein wenig herumgefummelt hatte, war das Geräusch des Wassereinfüllens aus der Richtung des Verschüttens zu hören, nach 2 Minuten ist die Flasche immer noch in der Füllphase, die übliche Schlange hat sich hinter uns gebildet und das Bild in meinem Kopf zeigt, wie fürsorglich Onkel ist Petya wählt nur die besten H2O-Moleküle für unsere Flasche aus. Der vom Leben geschulte Onkel Petja beruhigt die besonders Aggressiven und verspricht, so schnell wie möglich fertig zu werden. Nachdem er mit der Flasche fertig ist, nimmt er die nächste und stellt den üblichen Druck auf, der jedoch nicht alle Möglichkeiten des neuen Wasserhahns offenbart. Die Leute sind nicht glücklich... Mit Streams die Zeit schätzen – 1

Theorie

Multithreading ist die Fähigkeit einer Plattform, mehrere Threads innerhalb eines einzigen Prozesses zu erstellen. Das Erstellen und Ausführen eines Threads ist viel einfacher als das Erstellen eines Prozesses. Wenn also mehrere parallele Aktionen in einem Programm implementiert werden müssen, werden zusätzliche Threads verwendet. In der JVM wird jedes Programm im Hauptthread ausgeführt und der Rest wird von dort aus gestartet. Innerhalb desselben Prozesses können Threads Daten untereinander austauschen. Wenn Sie einen neuen Thread starten, können Sie ihn mithilfe der Methode als Benutzerthread deklarieren
setDaemon(true);
Solche Threads werden automatisch beendet, wenn keine anderen laufenden Threads mehr vorhanden sind. Threads haben Arbeitspriorität (die Wahl der Priorität garantiert nicht, dass der Thread mit der höchsten Priorität schneller abgeschlossen wird als der Thread mit der niedrigeren Priorität).
  • MIN_PRIORITÄT
  • NORM_PRIORITY (Standard)
  • MAX_PRIORITY
Grundlegende Methoden beim Arbeiten mit Streams:
  • run()– führt den Thread aus
  • start()– startet einen Thread
  • getName()– gibt den Thread-Namen zurück
  • setName()– gibt den Namen des Streams an
  • wait()notify()– geerbte Methode, der Thread wartet darauf, dass die Methode von einem anderen Thread aufgerufen wird
  • notify()– geerbte Methode, setzt einen zuvor gestoppten Thread fort
  • notifyAll()– geerbte Methode, setzt zuvor gestoppte Threads fort
  • sleep()– Pausiert den Stream für eine bestimmte Zeit
  • join()– wartet darauf, dass der Thread abgeschlossen ist
  • interrupt()– unterbricht die Thread-Ausführung
Weitere Methoden finden Sie hier. Es ist Zeit, über neue Threads nachzudenken, wenn Ihr Programm über Folgendes verfügt:
  • Netzwerkzugang
  • Zugriff auf das Dateisystem
  • GUI

Thread-Klasse

Threads werden in Java als Klasse Threadund ihre Nachkommen dargestellt. Das folgende Beispiel ist eine einfache Implementierung der Stream-Klasse.
import static java.lang.System.out;

public class ExampleThread extends Thread{

    public static void main(String[] args) {
        out.println("Основной поток");
        new ExampleThread().start();
    }

    @Override
    public void run() {
        out.println("Новый поток");
    }
}
Als Ergebnis erhalten wir
Основной поток
Новый поток
Hier erstellen wir unsere Klasse und machen sie zu einem Nachkommen der Klasse Thread. Anschließend schreiben wir die Methode main(), um den Hauptthread zu starten und die run()Klassenmethode zu überschreiben Thread. Nachdem wir nun eine Instanz unserer Klasse erstellt und ihre geerbte Methode ausgeführt haben, start()starten wir einen neuen Thread, in dem alles ausgeführt wird, was im Hauptteil der Methode beschrieben ist run(). Es klingt kompliziert, aber wenn man sich den Beispielcode ansieht, sollte alles klar sein.

Ausführbare Schnittstelle

Oracle schlägt außerdem vor, die Schnittstelle zu implementieren, um einen neuen Thread zu starten Runnable, was uns mehr Designflexibilität bietet als die einzige verfügbare Vererbung im vorherigen Beispiel (wenn Sie sich die Quelle der Klasse ansehen, Threadkönnen Sie sehen, dass sie auch die Schnittstelle implementiert Runnable). Lassen Sie uns die empfohlene Methode zum Erstellen eines neuen Threads verwenden.
import static java.lang.System.out;

public class ExampleRunnable implements Runnable {

    public static void main(String[] args) {
        out.println("Основной поток");
        new Thread(new ExampleRunnable()).start();
    }

    @Override
    public void run() {
        out.println("Новый поток");
    }
}
Als Ergebnis erhalten wir
Основной поток
Новый поток
Die Beispiele sind sehr ähnlich, weil Beim Schreiben des Codes mussten wir eine abstrakte Methode implementieren, die run()in der Schnittstelle beschrieben ist Runnable. Das Starten eines neuen Threads ist etwas anders. Wir haben eine Instanz der Klasse erstellt Thread, indem wir einen Verweis auf eine Instanz unserer Schnittstellenimplementierung als Parameter übergeben haben Runnable. Mit diesem Ansatz können Sie neue Threads erstellen, ohne die Klasse direkt zu erben Thread.

Lange Operationen

Das folgende Beispiel zeigt deutlich die Vorteile der Verwendung mehrerer Threads. Nehmen wir an, wir haben eine einfache Aufgabe, die mehrere langwierige Berechnungen erfordert. Vor diesem Artikel hätten wir sie in einer Methode gelöst und sie zur main()leichteren Wahrnehmung vielleicht in separate Methoden, vielleicht sogar in Klassen, zerlegt, aber das Wesentliche wäre dasselbe. Alle Operationen würden sequentiell nacheinander ausgeführt. Lassen Sie uns umfangreiche Berechnungen simulieren und deren Ausführungszeit messen.
public class ComputeClass {

    public static void main(String[] args) {
        // Узнаем стартовое время программы
        long startTime = System.currentTimeMillis();

        // Определяем долгосрочные операции
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 1");
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 2");
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 3");

        //Вычисляем и выводим время выполнения программы
        long timeSpent = System.currentTimeMillis() - startTime;
        System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
    }
}
Als Ergebnis erhalten wir
complete 1
complete 2
complete 3
программа выполнялась 9885 миллисекунд
Die Ausführungszeit lässt zu wünschen übrig, und die ganze Zeit sehen wir auf einen leeren Ausgabebildschirm, und die Situation ist der Geschichte über Onkel Petja sehr ähnlich, nur haben wir, die Entwickler, seine Rolle jetzt nicht ausgenutzt alle Möglichkeiten moderner Geräte. Wir werden uns verbessern.
public class ComputeClass {

    public static void main(String[] args) {
        // Узнаем стартовое время программы
        long startTime = System.currentTimeMillis();

        // Определяем долгосрочные операции
        new MyThread(1).start();
        new MyThread(2).start();
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete 3");

        //Вычисляем и выводим время выполнения программы
        long timeSpent = System.currentTimeMillis() - startTime;
        System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
    }
}

class MyThread extends Thread{
int n;

MyThread(int n){
    this.n = n;
}

    @Override
    public void run() {
        for(double i = 0; i < 999999999; i++){
        }
        System.out.println("complete " + n);
    }
}
Als Ergebnis erhalten wir
complete 1
complete 2
complete 3
программа выполнялась 3466 миллисекунд
Die Laufzeit wurde erheblich verkürzt (dieser Effekt wird möglicherweise nicht erreicht oder verlängert möglicherweise sogar die Ausführungszeit auf Prozessoren, die kein Multithreading unterstützen). Es ist zu beachten, dass Threads möglicherweise nicht in der richtigen Reihenfolge enden. Wenn der Entwickler Vorhersehbarkeit von Aktionen benötigt, muss er diese für einen bestimmten Fall unabhängig implementieren.

Thread-Gruppen

Threads können in Java zu Gruppen zusammengefasst werden, hierfür wird die Klasse verwendet ThreadGroup. Gruppen können sowohl einzelne Threads als auch ganze Gruppen umfassen. Dies kann praktisch sein, wenn Sie beispielsweise mit dem Netzwerk verbundene Flüsse unterbrechen müssen, wenn die Verbindung unterbrochen wird. Mehr über Gruppen können Sie hier lesen. Ich hoffe, dass Ihnen das Thema jetzt klarer geworden ist und Ihre Benutzer zufrieden sein werden.
Mit Streams die Zeit schätzen – 2
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION