$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.
@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(); } }
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(); } }
Und wenn Sie zum Starten die Methode $start()$ verwenden, handelt es sich um die echte Methode $run$, die vom Thread $t1$ ausgeführt wird.
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(); } }
Ausnahmeinformationen: #🎜 🎜#
# 🎜🎜#Schlafmethode und Ertragsmethode
@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
@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(); } }
$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);//该语句作用是睡眠一秒
Der 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 Programmewhile (true) { try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } }
Der Unterschied besteht darin, dass die beiden letzteren eine Sperre und eine entsprechende Aktivierung erfordern -Up-Operationen, die im Allgemeinen für das Synchronisierungsszenario $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("结束"); } }
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
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.
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.
打断$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()); } }
因此我们可以在线程中判断打断标记,来决定是否被打断,以及执行被打断之前的收尾工作。
@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(); } }
默认情况下,$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("主线程结束"); } }
如果不把$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!