Heim > Java > javaLernprogramm > Hauptteil

So verwenden Sie die Startmethode und die Ausführungsmethode in einem Java-Thread

WBOY
Freigeben: 2023-04-20 08:58:06
nach vorne
1591 Leute haben es durchsucht

    Startmethode und Ausführungsmethode

    $start()$-Methode wird verwendet, um einen Thread zu starten. Der Thread befindet sich im Status Ready (ausführbar) und wird nicht ausgeführt. Sobald die $cpu$-Zeitscheibe erhalten wurde, beginnt die Ausführung der Methode $run()$. Der direkte Aufruf der Methode $run()$ ruft nur eine Methode in einer Klasse auf, die im Wesentlichen im aktuellen Thread ausgeführt wird. Daher kann dies nur durch Verwendung der Methode $start()$ zum Aufrufen von $run()$ erreicht werden Methode. Echtes Multithreading.

    Beispielcode

    @Slf4j(topic = "c.Test4")
    public class Test4 {
        public static void main(String[] args) {
            Thread t1 = new Thread("t1"){
                @Override
                public void run() {
                    log.debug("running");
                }
            };
            t1.run();
        }
    }
    Nach dem Login kopieren

    Der obige Code ist ein direkter Aufruf der Methode $run()$. Den gedruckten Informationen können Sie entnehmen, dass der Thread $main$ diese Methode ausgeführt hat.

    @Slf4j(topic = "c.Test4")
    public class Test4 {
        public static void main(String[] args) {
            Thread t1 = new Thread("t1"){
                @Override
                public void run() {
                    log.debug("running");
                }
            };
            t1.start();
        }
    }
    Nach dem Login kopieren

    Und wenn Sie zum Starten die Methode $start()$ verwenden, handelt es sich um die echte Methode $run$, die vom Thread $t1$ ausgeführt wird.

    Hinweis

    Es ist zu beachten, dass das $Thread$-Objekt beim Aufrufen der $start()$-Methode in den Bereitschaftszustand wechselt und nicht erneut aufgerufen werden kann befindet sich im Bereitschaftszustand. Die Methode $start()$, andernfalls wird die Ausnahme $IllegalThreadStateException$ ausgelöst, wie im folgenden Code gezeigt:

    @Slf4j(topic = "c.Test4")
    public class Test4 {
        public static void main(String[] args) {
            Thread t1 = new Thread("t1"){
                @Override
                public void run() {
                    log.debug("running");
                }
            };
            t1.start();
            t1.start();
        }
    }
    Nach dem Login kopieren

    Ausnahmeinformationen: #🎜 🎜#

    # 🎜🎜#

    So verwenden Sie die Startmethode und die Ausführungsmethode in einem Java-ThreadSchlafmethode und Ertragsmethode

    Schlaf

      Calling the Die Methode $sleep()$ bewirkt, dass der aktuelle Thread vom Status $Running$ in den Status $Time Waiting$ (blockiert) wechselt Methode zum Unterbrechen des Schlafthreads. Zu diesem Zeitpunkt löst die $sleep$-Methode eine InterruptedException
    • Der Thread wird nach dem Schlafen möglicherweise nicht sofort ausgeführt
    • #🎜🎜 aus #

      Es wird empfohlen, $sleep$ von $TimeUnit$ anstelle von $sleep$ von $Thread$ zu verwenden, um eine bessere Lesbarkeit zu erzielen #
      @Slf4j(topic = "c.Test5")
      public class Test5 {
          public static void main(String[] args) {
              Thread t1 = new Thread("t1"){
                  @Override
                  public void run() {
                      try {
                          Thread.sleep(2000);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              };
              t1.start();
              log.debug("t1 state {}", t1.getState());
              //让主线程休眠500ms
              try {
                  Thread.sleep(500);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              log.debug("t1 state {}", t1.getState());
          }
      }
      //17:13:21.729 [main] DEBUG c.Test5 - t1 state RUNNABLE
      //17:13:22.245 [main] DEBUG c.Test5 - t1 state TIMED_WAITING
      Nach dem Login kopieren
    • Starten Sie im obigen Code den ersten $t1$-Thread. Zu diesem Zeitpunkt sollte sich der Status des Druckthreads im Status $RUNNABLE$ befinden. Wenn Sie den Hauptthread in den Ruhezustand versetzen, wird verhindert, dass der Hauptthread zuerst den Druck ausführt , ist aber noch nicht in den Zustand $sleep()$ eingetreten. Wenn die Methode $sleep$ in $run()$ ausgeführt wird, wechselt der Thread in den Zustand $TIMED WAITING$
    • @Slf4j(topic = "c.Test6")
      public class Thread6 {
          public static void main(String[] args) throws InterruptedException {
              Thread t1 = new Thread("t1") {
                  @Override
                  public void run() {
                      try {
                          log.debug("enter sleep");
                          Thread.sleep(2000);
                      } catch (InterruptedException e) {
                          log.debug("wake up");
                          e.printStackTrace();
                      }
                  }
              };
              t1.start();
              Thread.sleep(1000);
              log.debug("interrupt t1");
              //被唤醒
              t1.interrupt();
          }
      }
      Nach dem Login kopieren

      Ausführungsergebnis
    • #🎜🎜 #

    • Wenn im obigen Code die Methode $start$ gestartet wird, wechselt der Thread $t1$ in den Ruhezustand, druckt Eingabeaufforderungsinformationen, die Ruhezeit beträgt $2s$ und schläft im $main$-Thread Nach $1s$ wird der Ruhezustand des Threads $t1$ unterbrochen, die Unterbrechungsinformationen werden abgefragt und die Methode $interrupt()$ aufgerufen. Zu diesem Zeitpunkt wird der Thread unterbrochen und eine Ausnahme ausgelöst wird geworfen.

    $TimeUnit$-Klasse hat eine neue Einheit zum Schlafen hinzugefügt, die besser lesbar ist, aber im Wesentlichen gibt es keinen Unterschied, nur die Einheit wurde geändert geändert Conversion

    TimeUnit.SECONDS.sleep(1);//该语句作用是睡眠一秒
    Nach dem Login kopieren

    yield

    So verwenden Sie die Startmethode und die Ausführungsmethode in einem Java-ThreadDer Aufruf von $yield$ führt dazu, dass der aktuelle Prozess von $Running$ in den Bereitschaftszustand $Runnable$ übergeht und dann andere Threads plant und ausführt. Die spezifische Implementierung hängt vom Taskplaner des Systems ab (d. h. wenn keine anderen Tasks im Taskplaner vorhanden sind, wird der Thread auch dann weiter ausgeführt, wenn $cpu$ aufgegeben wird). Zu diesem Zeitpunkt wird die Ruhezeit nicht beendet, aber $yield$ wechselt in den Bereitschaftszustand, d. h. wenn kein anderer Thread ausgeführt werden muss. Dem Thread wird auch eine Zeitscheibe zugewiesen. Dies ist der größte Unterschied zwischen $sleep$- und $yield$-Threads Der Thread zuerst, aber es ist nur eine Eingabeaufforderung, der Scheduler kann ihn ignorieren

    Wenn $cpu$ relativ ausgelastet ist, erhält der Thread mit der höheren Priorität mehr Zeitscheiben, aber wenn $cpu$ inaktiv ist, wird der Die Priorität wird fast Null sein. 🎜#Wenn $cpu$ nicht für die Berechnung verwendet wird, lassen Sie $while(true)$ nicht im Leerlauf und verschwenden Sie $cpu$. Zu diesem Zeitpunkt können Sie $yield$ oder $sleep$ verwenden über die Nutzungsrechte von $cpu$ an andere Programme

    while (true) {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
      }
    }
    Nach dem Login kopieren

    Sie können $wait$ oder Bedingungsvariablen verwenden, um ähnliche Effekte zu erzielen

    Der Unterschied besteht darin, dass die beiden letzteren eine Sperre und eine entsprechende Aktivierung erfordern -Up-Operationen, die im Allgemeinen für das Synchronisierungsszenario So verwenden Sie die Startmethode und die Ausführungsmethode in einem Java-Thread$sleep$ geeignet sind, eignen sich für Szenarien, die keine Sperrsynchronisierung erfordern

    Join-Methode

    Druckergebnisse des folgenden Programms:

    #🎜🎜 #

    @Slf4j(topic = "c.Test6")
    public class Test6 {
        static int r = 0;
        public static void main(String[] args) {
            test();
        }
        private static void test() {
            log.debug("开始");
            Thread t = new Thread("t1") {
                @Override
                public void run() {
                    log.debug("开始");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    log.debug("结束");
                    r = 10;
                }
            };
            t.start();
            log.debug("r的值是{}", r);
            log.debug("结束");
        }
    }
    Nach dem Login kopieren

    Da der Hauptthread und der $t1$-Thread parallel sind, ist der $t1$-Thread benötigt $1s$, um den Wert von $r$ zu berechnen, und der Hauptthread benötigt $1s$, um den Wert von $r$ zu berechnen. Der Thread gibt den Wert von $r$ am Anfang aus, also ist der gedruckte Wert 0

    Lösung:

    Fügen Sie einfach $t.join();$ nach start();$ hinzu. Die Funktion von $join$ besteht darin, darauf zu warten, dass die Ausführung eines Threads beendet ist.

    Aus Sicht des Aufrufers ist es synchron, auf die Rückgabe des Ergebnisses zu warten, bevor die Ausführung fortgesetzt wird, und es ist asynchron, die Ausführung fortzusetzen, ohne auf die Rückgabe des Ergebnisses zu warten.

    Die $join$-Methode sorgt also tatsächlich dafür, dass sie synchron ausgeführt wird

    Effektives Warten#🎜 🎜#$ Die Methode „join(milliseconds)$“ kann einen Parameter haben, der in der Wartezeit übergeben wird. Wenn die Thread-Ausführungszeit länger als die Wartezeit ist, wird das Warten nach Ablauf der Wartezeit beendet. Wenn die Thread-Ausführungszeit kürzer als die Wartezeit ist, endet das Warten, nachdem die Thread-Ausführung abgeschlossen ist. Die eingestellte Wartezeit läuft nicht ab.

    interrupt方法

    打断$sleep, wait, join$的线程,即打断阻塞状态的线程
    打断$sleep$的线程,会清空打断状态

    @Slf4j(topic = "c.Test7")
    public class Test7 {
        public static void main(String[] args) throws InterruptedException {
            Thread t = new Thread("t1"){
                @Override
                public void run() {
                    log.debug("sleep...");
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
            t.start();
            Thread.sleep(1000);
            log.debug("interrupt");
            t.interrupt();
            log.debug("打断标记: {}", t.isInterrupted());
        }
    }
    Nach dem Login kopieren

    So verwenden Sie die Startmethode und die Ausführungsmethode in einem Java-Thread

    打断正常运行的线程,不会清空打断状态

    因此我们可以在线程中判断打断标记,来决定是否被打断,以及执行被打断之前的收尾工作。

    @Slf4j(topic = "c.Test8")
    public class Test8 {
        public static void main(String[] args) throws InterruptedException {
            Thread t = new Thread("t1"){
                @Override
                public void run() {
                    while (true) {
                        if (Thread.currentThread().isInterrupted()) {
                            log.debug("线程被打断了");
                            break;
                        }
                    }
                }
            };
            t.start();
            Thread.sleep(1000);
            log.debug("interrupt");
            t.interrupt();
        }
    }
    Nach dem Login kopieren

    守护线程

    默认情况下,$java$需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其他非守护线程运行结束了,即使守护线程的代码没有执行完毕,也会强制结束。

    @Slf4j(topic = "c.Test10")
    public class Test10 {
        public static void main(String[] args) throws InterruptedException {
            Thread t = new Thread("t1") {
                @Override
                public void run() {
                    while (true) {
    
                    }
                }
            };
            //设置线程为守护线程
            t.setDaemon(true);
            t.start();
            Thread.sleep(1000);
            log.debug("主线程结束");
        }
    }
    Nach dem Login kopieren

    如果不把$t$设置为守护线程,则因为线程内部的死循环,导致程序不会结束运行。

    Das obige ist der detaillierte Inhalt vonSo verwenden Sie die Startmethode und die Ausführungsmethode in einem Java-Thread. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Verwandte Etiketten:
    Quelle:yisu.com
    Erklärung dieser Website
    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
    Beliebte Tutorials
    Mehr>
    Neueste Downloads
    Mehr>
    Web-Effekte
    Quellcode der Website
    Website-Materialien
    Frontend-Vorlage