Heim  >  Artikel  >  Java  >  Vier Möglichkeiten, den Hauptthread herunterzufahren, nachdem alle Unterthread-Aufgaben abgeschlossen sind

Vier Möglichkeiten, den Hauptthread herunterzufahren, nachdem alle Unterthread-Aufgaben abgeschlossen sind

坏嘻嘻
坏嘻嘻Original
2018-09-14 16:27:434129Durchsuche

Multithreading ist ein sehr wichtiger Wissenspunkt in Java. Ich hoffe, dass Sie es beherrschen.

    • Methode eins Thread.sleep

    • Methode zwei ExecutorService

    • Methode drei Thread .join

    • Methode 4 Thread.yield und Thread.activeCount


Ich bin beim Schreiben von Code auf ein solches Szenario gestoßen. Ich muss den Ausführungsstatus jedes Unterthreads beobachten. Wenn keine Verarbeitung durchgeführt wird, werden andere Unterthreads nach der main-Methode geschlossen ist mit der Ausführung fertig, wodurch es unmöglich ist, den detaillierten Ausführungsstatus aller Unterthreads zu beobachten, sodass der Hauptthread warten muss, bis die Ausführung aller Unterthreads abgeschlossen ist. In der Vergangenheit bestand der schlampigere Ansatz darin, main zur Funktion Thread.sleep(time) Diese Methode ist jedoch nicht perfekt, da die künstliche Einstellung der Wartezeit nicht die beste Vorgehensweise ist. Daher habe ich einige Informationen und Blogs überprüft. Hier sind vier Methoden, um diesen Zweck zu erreichen >

Methode 1 Thread.sleep

Dies sollte die gebräuchlichste Methode sein, obwohl es nicht die beste Methode ist, kann es kaum die Anforderungen erfüllen:

public static void main(String[] args) throws InterruptedException{        for(int i=0; i<10; i++){            new Thread("subthread" + i){
                @Override                public void run() {                    try {
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName() + "finished");
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }.start();
        }
        Thread.sleep(2000);
        System.out.println("main thread finished");
    }

Methode 2 ExecutorService

kann die Thread-Pool-Implementierung verwenden. Häufig verwendete Thread-Pool-Objekte sind alle Implementierungen der

-Schnittstelle, die Methoden wie

bereitstellt, um sicherzustellen, dass Java Der Prozess wird normal beendet, nachdem die Ausführung der aktuell übermittelten Aufgabe im untergeordneten Thread abgeschlossen ist. Das Ergebnis ist:

subthread0finished
subthread1finished
subthread2finished
subthread6finished
subthread4finished
subthread5finished
subthread3finished
subthread9finished
subthread8finished
subthread7finished
main thread finished
ExecutorService Diese Methode weist einige kleinere Mängel auf Der Hauptthread wird tatsächlich vor dem untergeordneten Thread ausgeführt. Daher kann diese Methode nur sicherstellen, dass der untergeordnete Thread vollständig ausgeführt wird, bevor das Programm beendet wird. Es gibt jedoch keine Garantie dafür, dass der Hauptthread ausgeführt wird, nachdem der untergeordnete Thread ausgeführt wurde. Die Ausführung des Threads ist abgeschlossen. Daher muss der Code geändert werden, um eine angemessenere Wartezeit festzulegen und darauf zu warten, dass die Ausführung des Unterthreads abgeschlossen ist: shutdown
public static void main(String[] args) {        // 创建一个ExecutorService
        ExecutorService ex =  Executors.newCachedThreadPool();        for(int i=0; i<10; i++){            // 添加 task
            ex.submit(new Thread("subthread" + i){

                @Override                public void run() {                    try{
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName() + "finished");
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            });
        }        // 使用shutdown 会通知executorservice 停止添加其它task 它会等待所有子线程运行结束才退出Java进程
        ex.shutdown();
        System.out.println("main thread finished");

    }

Sie können sehen, dass der vom Hauptthread ausgeführte Inhalt am Ende ausgegeben wird. Diese Methode muss die Wartezeit wie Methode 1 festlegen, was keine perfekte Methode ist.

Methode 3 Thread. join

awaitTermination(time, timeunit)

bedeutet, dass sich der Thread, der diesen Code ausführt, in einem angehaltenen Zustand befindet und darauf wartet, dass der Thread, der diese Methode aufruft (hier dieser Thread), die Ausführung beendet, bevor er mit der Ausführung fortfährt. Die folgenden Beispiel-Neutronen-Threads sind Alles wurde im

-Thread erstellt. Wenn also

im

-Thread ausgeführt wird, wird gewartet, bis die Ausführung des untergeordneten Threads abgeschlossen ist, bevor mit der Ausführung des

-Threads fortgefahren wird. Der Code lautet wie folgt:

main thread finished
pool-1-thread-3finished
pool-1-thread-4finished
pool-1-thread-2finished
pool-1-thread-1finished
pool-1-thread-5finished
pool-1-thread-7finished
pool-1-thread-8finished
pool-1-thread-6finished
pool-1-thread-9finished
pool-1-thread-10finished

Laufergebnisse:

public static void main(String[] args) {        // 创建一个ExecutorService
        ExecutorService ex =  Executors.newCachedThreadPool();        for(int i=0; i<10; i++){            // 添加 task
            ex.submit(new Thread("subthread" + i){

                @Override                public void run() {                    try{
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName() + "finished");
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            });
        }        // 使用shutdown 会通知executorservice 停止添加其它task 它会等待所有子线程运行结束才退出Java进程
        ex.shutdown();        try {            // 设置等待时间等待子线程运行完毕
            if(!ex.awaitTermination(2000, TimeUnit.MILLISECONDS)){                // 等待时间内子线程并未全部运行完毕就直接关闭
                ex.shutdownNow();
            }
        }catch(InterruptedException e){
            ex.shutdownNow();
        }

        System.out.println("main thread finished");

    }
thread.joinDer Vorteil dieser Methode im Vergleich zu den beiden oben genannten Methoden besteht darin, dass keine Wartezeit festgelegt werden muss.mainmainMethode 4 Thread.yield und Thread.activeCount某一个子线程.joinmainErklären wir zunächst die Funktionen dieser beiden Methoden. Für Laien ist

eine Konzession. Der aktuelle Thread

, der diese Methode aufruft, belegt die Rechte von

. Dies bedeutet jedoch nicht, dass der aktuelle Thread nicht mehr ausgeführt wird. Die Methode

gibt die Anzahl der aktiven Threads in der Thread-Gruppe zurück, die dem aktuell aufrufenden Thread entspricht. Der Parameter

bezieht sich auf die Thread-Gruppe, die dem erstellten Thread entspricht. Wenn dieser Parameter nicht angegeben ist, befindet sich der Thread, der erstellt wurde, in derselben Thread-Gruppe. Der Code lautet wie folgt:

pool-1-thread-1finished
pool-1-thread-5finished
pool-1-thread-4finished
pool-1-thread-9finished
pool-1-thread-8finished
pool-1-thread-3finished
pool-1-thread-2finished
pool-1-thread-7finished
pool-1-thread-6finished
pool-1-thread-10finished
main thread finished

Laufergebnis:

public static void main(String[] args) throws InterruptedException{
        List<Thread> list = new ArrayList<>();        for(int i=0; i<10; i++){
            Thread t = new Thread("subthread" + i){
                @Override                public void run() {                    try{
                        Thread.sleep(3000);
                        System.out.println(Thread.currentThread().getName() + "finished");
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            };
            list.add(t);
            t.start();
        }        for(Thread item : list){
            item.join();
        }
        System.out.println("main thread finished");
    }
Thread.yieldEin sehr wichtiger Punkt ist, dass 放弃 auf 2 gesetzt ist. Ja. Einige Blogs setzen es auf 1, aber 1 führt zu einer Endlosschleife und der Hauptthread kann dies nicht Der Grund dafür ist, dass jeder denkt, dass nach dem Ausschließen der Sub-Threads in der Thread-Gruppe, in der sich der Haupt-Thread befindet, nur noch der Haupt-Thread übrig ist. Dies ist beispielsweise nicht der Fall, wenn wir Folgendes ausführen Code: CPU
subthread1finished
subthread2finished
subthread0finished
subthread3finished
subthread6finished
subthread5finished
subthread4finished
subthread9finished
subthread7finished
subthread8finished
main thread finished
Thread.activeCount Ausgabe: ThreadGroup
public static void main(String[] args) {        // 关键参数
        int defaultThreadNum = 2;        for(int i=0; i<10 ;i++){            new Thread("subthread" + i){
                @Override                public void run() {                    try {
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName() + "finished");
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }.start();
        }        while(Thread.activeCount() > defaultThreadNum){            // 当活跃线程数大于设定的默认线程数的时候 主线程让步
            Thread.yield();
        }
        System.out.println("main thread finished");
    }

Sie können sehen, dass es in der Thread-Gruppe, in der sich der Haupt-Thread befindet, einen weiteren Thread namens

gibt. Nach dem Ausschließen aller untergeordneten Threads gibt es also einen Es sind noch 2 Threads übrig, daher muss der Schwellenwert für die Schleifenbeurteilung (

) auf 2 gesetzt werden.

Diese Methode muss auch nicht die Wartezeit festlegen defaultthreadnum

Zusammenfassend, falls erforderlich Um den Hauptthread in allen Unterthreads zu implementieren, können Sie Methode drei und Methode vier verwenden, um ihn nach Abschluss des Vorgangs erneut auszuführen.

Monitor Ctrl-BreakdefaultThreadNum

Verwandte Empfehlungen:

Umfassende Analyse von Java Thread Multithreading

php5 non -Der Unterschied zwischen Thread-sicher und Thread-sicher

Das obige ist der detaillierte Inhalt vonVier Möglichkeiten, den Hauptthread herunterzufahren, nachdem alle Unterthread-Aufgaben abgeschlossen sind. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn