[JavaEE] Multithreading in Java (Thread-Klasse)

Homepage des Autors:paper jie_blog

Autor dieses Artikels: Hallo zusammen, ich bin Papier-Jie. Vielen Dank, dass Sie diesen Artikel gelesen haben. Willkommen bei Yijiansanlian.

Dieser Artikel ist in der Spalte „JavaEE“ enthalten. Diese Spalte wurde sorgfältig für Studenten und Programmieranfänger erstellt. Der Autor hat viel Geld (Zeit und Energie) investiert, um es zu erstellen und alle Grundkenntnisse von MySQL abzudecken. Ich hoffe, es kann den Lesern helfen.

Andere Spalten: „MySQL“, „C Language“, „javaSE“, „Data Structure“ usw.

Inhaltsfreigabe: In dieser Ausgabe wird ein wichtiger Multithreading-Klassen-Thread in JavaEE~ geteilt

Inhaltsverzeichnis

Was ist Thread

Erstelle einen Thread

Erben Sie die Thread-Klasse

Implementieren Sie die Runnable-Schnittstelle

Die anonyme innere Klasse erstellt ein Thread-Unterklassenobjekt

Die anonyme innere Klasse erstellt ein ausführbares Unterklassenobjekt

Der Lambda-Ausdruck erstellt ein Unterklassenobjekt

Thread-Klassenmethoden und allgemeine Attribute

Konstruktionsmethode

Gemeinsame Eigenschaften

Gängige Methoden

Einen Thread starten - start()

Thread unterbrechen 

Einführung von Tags

unterbrechen()

Grund für die Ausnahme

Wartendes Programm - join()

Holen Sie sich die aktuelle Thread-Referenz - currentThread()


Was ist Thread

Die Thread-Klasse befindet sich in der Java-Standardbibliothek und kann als weitere Abstraktion und Kapselung der vom Betriebssystem bereitgestellten API betrachtet werden. Wir können uns ein Thread-Instanzobjekt als Thread vorstellen.

Erstelle einen Thread

Erben Sie die Thread-Klasse

Hier müssen Sie eine Thread-Klasse erstellen, die der Thread-Klasse folgt, da hier die Ausführungsmethode überschrieben werden muss, die die Logik enthält, die dieser Thread ausführen muss.

Dann müssen Sie eine Instanz davon erstellen, damit ein Thread erstellt werden kann. Schließlich müssen Sie die Startmethode aufrufen, um den Thread zu starten.

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("hello Thread");

    }
}
public class ThreadDemo1 {
    public static void main(String[] args) {
        Thread t = new MyThread();
        t.start();
        System.out.println("hello main");
         
    }
}

Implementieren Sie die Runnable-Schnittstelle

Erstellen Sie eine Thread-Instanz und übergeben Sie das Runnable-Objekt als Parameter, wenn Sie den Thread-Konstruktor aufrufen.

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程运行代码");
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        t.start();
        System.out.println("hell main");

    }
}

Die anonyme innere Klasse erstellt ein Thread-Unterklassenobjekt

Dahinter verbirgt sich eine anonyme Unterklasse der Thread-Klasse.

public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread t = new Thread("这是我"){
            @Override
            public void run() {
                System.out.println("这是匿名方法");
                while(true) {
                    System.out.println("heeh");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        t.start();
    }
}

Die anonyme innere Klasse erstellt ein ausführbares Unterklassenobjekt

public class ThreadDemo4 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable(){
            @Override
            public void run() {
                System.out.println("匿名创建Runnable子类");
            }
        });
        t.start();
    }
}

Der Lambda-Ausdruck erstellt ein Unterklassenobjekt

public class ThreadDemo5 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("lambda表达式创建子类对象");
        });
        t.start();
    }
}

Thread-Klassenmethoden und allgemeine Attribute

Konstruktionsmethode

Der dritte und vierte hier können zum besseren Debuggen umbenannt werden.

Gemeinsame Eigenschaften

Die ID ist die eindeutige Darstellung dieses Threads und unterschiedliche Thread-IDs werden nicht wiederholt.

Der Name wird im Allgemeinen beim Debuggen verwendet.

Der Status stellt die aktuelle Situation eines Threads dar. Im Allgemeinen gibt es einen Bereitschaftsstatus und einen Blockierungsstatus.

Die Priorität gibt an, ob es wahrscheinlicher ist, dass ein Thread geplant wird

Die Ausführung des Vordergrund-Threads verhindert das Ende des Prozesses, und die Ausführung des Hintergrund-Threads verhindert nicht das Ende des Prozesses. Das Ende eines Prozesses ist erforderlich um zu warten, bis die Ausführung aller Vordergrund-Threads abgeschlossen ist. Andernfalls wird der Haupt-Thread nicht beendet, selbst wenn er ausgeführt wird. Die von uns erstellten Threads sind standardmäßig alle Vordergrund-Threads.

Ob sie aktiv ist oder nicht, hängt einfach davon ab, ob die Ausführungsmethode ausgeführt wurde. Obwohl die Thread-Instanz in Java Multithreading darstellt, sind ihr Lebenszyklus und die in erstellte Thread-PCB Der Kernel Die Lebenszyklen sind nicht die gleichen.

Obwohl das Thread-Instanzobjekt zu diesem Zeitpunkt vorhanden ist, wurde der Thread im Kernel noch nicht erstellt und isAlive ist falsch. Der Thread im Kernel wird erst erstellt, nachdem t.start() ausgeführt wurde, und isAlive ist zu diesem Zeitpunkt wahr Zeit.

Wenn die Ausführungsmethode ausgeführt wird, wird der Thread im Kernel zerstört und isAlive ist zu diesem Zeitpunkt falsch.

Gängige Methoden

Einen Thread starten - start()

Obwohl das Thread-Instanzobjekt hier erstellt wird, wird der Thread nicht tatsächlich gestartet. Ein Thread wird erst dann wirklich erstellt, wenn start() aufgerufen wird. Der Start (hier) ist die Erstellung ein Thread im Kernel. Der Aufruf von start() zum Erstellen eines Threads ist im Wesentlichen der Aufruf der System-API zum Erstellen eines Threads.

Hier kann ein Thread start() nur einmal aufrufen. Um start erneut zu verwenden, müssen Sie ihn mit einem anderen Thread-Objekt aufrufen. Andernfalls wird eine Ausnahme mit ungültigem Thread-Status gemeldet.

public class ThreadDemo1 {
    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("线程");
            }
        };
        thread.start();
        thread.start();
        System.out.println("hell main");
    }
}

Thread unterbrechen 

Das Unterbrechen eines Threads bedeutet, dass die Ausführungsmethode des Threads vorzeitig beendet wird. Es gibt zwei häufig verwendete Methoden:

1. Durch die Einführung eines Tags

2. Über die Methode interrupt()

Einführung von Tags

Hier wird das Flag verwendet, um die Ausführungsmethode vorzeitig zu beenden. Wenn der Hauptthread flag = true ausführt, wird der andere Thread vorzeitig beendet.

public class ThreadDemo2 {
    public static  boolean flag = false;
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while(!flag) {
                    System.out.println("hell Thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("终止这个线程");
        flag = true;
    }
}

Beachten Sie hier, dass die Flag-ID nicht in die Hauptmethode aufgenommen und nicht als lokale Variable verwendet werden kann. Obwohl die anonyme innere Lambda-Klasse über die Variablenerfassung auf externe lokale Variablen zugreifen kann, muss diese lokale Variable unveränderlich und endgültig geändert werden. Dies steht in Konflikt mit Wir müssen den Thread beenden, indem wir die Markierung ändern, was nicht möglich ist.

Es muss endgültig sein, da die Hauptmethode und der Thread ihre eigenen Funktionsstapelrahmen haben. Ihre Lebenszyklen sind unterschiedlich Verwenden Sie es erneut. Es wird nicht mehr benötigt. Die Variablenerfassung hier wurde zu diesem Zweck entwickelt. Dabei werden Parameter übergeben, die im Wesentlichen das Flag im erforderlichen Thread kopieren. Um die Konsistenz des Flags sicherzustellen, kann es nicht geändert werden.

unterbrechen()

Der Thread wird mit einem Flag geliefert. Wir können dieses Flag über Methoden erhalten und ändern.

Hier können Sie Thread.interrupted() oder Thread.currentThread().isInterrupted() verwenden, um das integrierte Flag-Bit abzurufen.

Die Methode interrupt() kann das Flag-Bit ändern.

Thread.currentThread().isterrupted wird hier verwendet:

public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while(!Thread.currentThread().isInterrupted()) {
                System.out.println("hell Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("中断它");
        thread.interrupt();

    }
}

Aber nachdem wir den Code ausgeführt haben, werden wir das Problem finden:

Hier werden Sie feststellen, dass eine Interrupt-Ausnahme ausgelöst wird und die Ausführung dann ohne Unterbrechung fortgesetzt wird.

Grund für die Ausnahme

Da die Interrupt () -Methode hier den Schlaf im Voraus aufweckt, führt der Schlaf zu diesem Zeitpunkt zwei Dinge aus:

1. Lösen Sie die InterruptedExecption-Ausnahme aus

2. Stellen Sie das integrierte Flag-Bit wieder her.

All dies führt dazu, dass der Thread weiterläuft.

Wenn der Thread angehalten werden muss, können wir einfach eine Pause in den Catch einfügen.

Hier haben wir drei Verarbeitungsmethoden in Catch:

1. Lassen Sie den Faden sofort stoppen

2. Lassen Sie den Thread Code ausführen, bevor Sie ihn stoppen

3. Lassen Sie den Thread weiterlaufen, ohne anzuhalten

 Wir haben auch mehrere gängige Methoden zur Behandlung von Ausnahmen:

Wartendes Programm - join()

Die Join-Methode kann die Ausführungsreihenfolge von Threads anpassen. Obwohl die Planung der Thread-Ausführung zufällig geplant ist, kann Join hier die Threads blockieren, was sich auf die Ausführungsreihenfolge von Threads auswirkt. Der Thread, in dem sich Join befindet, wird blockiert. Nach dem Aufruf die Join-Methode Nachdem der Thread die Ausführung beendet hat, wird der Blockierungsstatus dieses Threads freigegeben.

Hinweis: Hier wird darauf gewartet, dass der Thread, der join() aufruft, zuerst ausgeführt wird, und der Thread, in dem sich join() befindet, wartet und wird später ausgeführt.

Es gibt drei join()-Methoden:

Der erste Typ: Wenn Sie zu Tode warten, müssen Sie warten, bis die Ausführung des wartenden Threads abgeschlossen ist, bevor der Blockierungsstatus aufgehoben wird.

Der zweite Typ: Warten auf einen bestimmten Zeitraum, Blockieren innerhalb eines bestimmten Zeitraums. Wenn der Zeitbereich überschritten wird, wird der Blockierungszustand aufgehoben.

Der dritte Typ: Es gibt eine mikrosekundengenaue Wartezeit.

Unter normalen Umständen verwenden wir am häufigsten den zweiten Fall:

public class ThreadDemo4 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while(true) {
                System.out.println("hell main");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
        thread.join();
        while(true) {
            System.out.println("hell ");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }
    }
}

Dieser Code bedeutet, dass der Hauptthread in den Blockierungszustand wechselt und auf das Ende des Thread-Threads wartet. Obwohl der Thread-Thread während der Ausführung zusammen mit mehreren anderen Threads geplant und ausgeführt werden kann, da der Haupt-Thread gewartet hat, auch wenn der Thread-Thread läuft auf der CPU Auch wenn Sie mehrmals wechseln, hat dies zunächst keine Auswirkungen auf die Ausführung dieses Threads.

Beachten Sie hier: Unsere Interrupt-Methode kann den Join-Thread im Voraus aktivieren.

Holen Sie sich die aktuelle Thread-Referenz - currentThread()

 Wenn wir die Klassenvererbung Thread verwenden, um eine Thread-Methode zu erstellen, können wir diese verwenden, um direkt auf das Objekt zu verweisen. Bei Verwendung von Lambda/anonymer innerer Klasse/Runnable zeigt dies jedoch nicht mehr auf das Thread-Objekt. Zu diesem Zeitpunkt müssen wir verwenden currentThread(), um die Thread-Objektreferenz abzurufen. Die Methode. 

public class ThreadDemo7 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            System.out.println("hello Thread");
            System.out.println(Thread.currentThread().getName());
        });
        t.start();
    }
}

Den aktuellen Thread in den Ruhezustand versetzen - sleep() 

sleep kann den aktuellen Thread für einen bestimmten Zeitraum in den Ruhezustand versetzen. Diese Zeit kann von Ihnen selbst festgelegt werden. Für die Verwendung ist jedoch das Auslösen einer Ausnahme oder ein Try-Catch erforderlich.Die Ruhezeit Dies liegt an der Thread-Planung, die nicht kontrollierbar ist und normalerweise größer oder gleich der eingestellten Zeit ist.

Es gibt auch zwei Methoden:

Im Allgemeinen wird die erste verwendet und die zweite ist auf Mikrosekunden genau.

public class ThreadDemo8 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            try {
                Thread.sleep(1111);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("休眠1.111秒");
        });
        t.start();
    }
}

Supongo que te gusta

Origin blog.csdn.net/paperjie/article/details/134552957
Recomendado
Clasificación