/** * <p> * start() 和 run() 的比较 * </p> * * @author 踏雪彡寻梅 * @version 1.0 * @date 2020/9/20 - 16:15 * @since JDK1.8 */public class StartAndRunMethod { public static void main(String[] args) { // run 方法演示 // 输出: name: main // 说明由主线程去执行的, 不符合新建一个线程的本意 Runnable runnable = () -> { System.out.println("name: " + Thread.currentThread().getName()); }; runnable.run(); // start 方法演示 // 输出: name: Thread-0 // 说明新建了一个线程, 符合本意 new Thread(runnable).start(); } }复制代码
Verwenden Sie die Methode
run
direkt wird kein neuer Thread eröffnet. (falscher Weg)start
-Methode startet einen neuen Thread. (Richtige Vorgehensweise)run
方法不会启动一个新线程。(错误方式)
start
方法会启动一个新线程。(正确方式)
start
方法可以启动一个新线程。
start
方法之后, 当前线程(通常是主线程)会请求 JVM 虚拟机如果有空闲的话来启动一下这边的这个新线程。start
方法,也不一定能够立刻的启动线程。srtart
方法调用之后,并不意味这个方法已经开始运行了。它可能稍后才会运行,也很有可能很长时间都不会运行,比如说遇到了饥饿的情况。start
方法,而线程 2 后调用了 start
方法,却发现线程 2 先执行线程 1 后执行的情况。start
方法的顺序并不能决定真正线程执行的顺序。start
方法会牵扯到两个线程。start
方法,第二个才是新的线程。start
就已经是子线程去执行了,这个语句其实是主线程或者说是父线程来执行的,被执行之后才去创建新线程。start
方法创建新线程的准备工作
run
方法中的代码。需要注意: 不能重复的执行 start 方法
代码示例
/** * <p> * 演示不能重复的执行 start 方法(两次及以上), 否则会报错 * </p> * * @author 踏雪彡寻梅 * @version 1.0 * @date 2020/9/20 - 16:47 * @since JDK1.8 */public class CantStartTwice { public static void main(String[] args) { Runnable runnable = () -> { System.out.println("name: " + Thread.currentThread().getName()); }; Thread thread = new Thread(runnable); // 输出: name: Thread-0 thread.start(); // 输出: 抛出 java.lang.IllegalThreadStateException // 即非法线程状态异常(线程状态不符合规定) thread.start(); } }复制代码
报错的原因
start
一旦开始执行,线程状态就从最开始的 New 状态进入到后续的状态,比如说 Runnable,然后一旦线程执行完毕,线程就会变成终止状态,而终止状态永远不可能再返回回去,所以会抛出以上异常,也就是说不能回到初始状态了。这里描述的还不够清晰,让我们来看看源码能了解的更透彻。public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ // 第一步, 检查线程状态是否为初始状态, 这里也就是上面抛出异常的原因 if (threadStatus != 0) throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ // 第二步, 加入线程组 group.add(this); boolean started = false; try { // 第三步, 调用 start0 方法 start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } }复制代码
第一步:启动新线程时会首先检查线程状态是否为初始状态, 这也是以上抛出异常的原因。即以下代码:
if (threadStatus != 0) throw new IllegalThreadStateException();复制代码
其中 threadStatus
这个变量的注释如下,也就是说 Java 的线程状态最初始(还没有启动)的时候表示为 0:
/* Java thread status for tools, * initialized to indicate thread 'not yet started' */private volatile int threadStatus = 0;复制代码
第二步:将其加入线程组。即以下代码:
group.add(this);复制代码
第三步:最后调用 start0()
这个 native 方法(native 代表它的代码不是由 Java 实现的,而是由 C/C++ 实现的,具体实现可以在 JDK 里面看到,了解即可), 即以下代码:
boolean started = false;try { // 第三步, 调用 start0 方法 start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } }复制代码
@Overridepublic void run() { // 传入了 target 对象(即 Runnable 接口的实现), 执行传入的 target 对象的 run 方法 if (target != null) { target.run(); } }复制代码
第一种: 重写了 Thread
类的 run
方法,Thread
的 run
方法会失效, 将会执行重写的 run
start
kann einen neuen Thread starten. 🎜🎜🎜Nachdem das Thread-Objekt nach der Initialisierung die Methode start
aufruft, fordert der aktuelle Thread (normalerweise der Hauptthread) die virtuelle JVM-Maschine auf, diesen neuen Thread zu starten, wenn er frei ist. 🎜🎜Mit anderen Worten: Das Wesentliche beim Starten eines neuen Threads besteht darin, die JVM aufzufordern, diesen Thread auszuführen. 🎜🎜Was den Zeitpunkt betrifft, an dem dieser Thread ausgeführt werden kann, wird nicht einfach von uns entschieden, sondern vom Thread-Scheduler. 🎜🎜Wenn es sehr beschäftigt ist, können wir den Thread möglicherweise nicht sofort starten, selbst wenn wir die Methode start
ausführen. 🎜🎜Nachdem die Methode srtart
aufgerufen wurde, bedeutet dies nicht, dass diese Methode mit der Ausführung begonnen hat. Es kann sein, dass es erst später oder längere Zeit nicht läuft, beispielsweise bei Hunger. 🎜🎜Dies beweist auch, dass in einigen Fällen Thread 1 zuerst die Methode start
aufruft und dann Thread 2 die Methode start
aufruft, sich jedoch herausstellt, dass Thread 2 die Methode ausführt Thread zuerst 1 nach der Ausführung. 🎜🎜Zusammenfassung: Die Reihenfolge, in der die Methode start
aufgerufen wird, bestimmt nicht die Reihenfolge, in der die tatsächlichen Threads ausgeführt werden. Die 🎜🎜🎜Notes🎜🎜🎜start
-Methode umfasst zwei Threads. 🎜🎜Der erste ist der Hauptthread, denn wir müssen einen Hauptthread oder andere Threads haben (auch wenn es nicht der Hauptthread ist), um diese start
-Methode auszuführen, und der zweite ist der neue Faden. 🎜🎜In vielen Fällen wird der Hauptthread, der den Thread für uns erstellt, ignoriert. Denken Sie nicht fälschlicherweise, dass der Aufruf von start
bedeutet, dass er bereits vom untergeordneten Thread ausgeführt wird Zur Ausführung wird ein neuer Thread erstellt. 🎜🎜🎜🎜🎜start
-Methode zum Erstellen einer neuen Thread-Vorbereitung 🎜🎜🎜Zuerst wird es sich selbst in den Bereitschaftszustand versetzen. 🎜🎜Der Bereitschaftsstatus bedeutet, dass neben der CPU auch andere Ressourcen abgerufen wurden, z. B. Kontext, Stapel, Thread-Status und PC (PC ist ein Register, PC zeigt auf den Speicherort, an dem das Programm ausgeführt wird) usw. wurden festgelegt . 🎜🎜🎜Nach Abschluss dieser Vorbereitungen ist alles bereit und alles, was wir brauchen, ist Dongfeng, die CPU-Ressource. 🎜🎜Nach Abschluss der Vorbereitungsarbeiten kann der Thread von der JVM oder dem Betriebssystem weiter in den Ausführungsstatus versetzt werden, um auf CPU-Ressourcen zu warten, und dann tatsächlich in den Ausführungsstatus wechseln, um den Code im run-Methode. 🎜🎜🎜🎜🎜Hinweis: Die Startmethode kann nicht wiederholt ausgeführt werden🎜🎜🎜🎜🎜Codebeispiel🎜rrreee🎜🎜🎜Der Grund für den Fehler🎜🎜🎜<code>start
Sobald die Ausführung beginnt, Der Thread-Status Geben Sie einfach den nachfolgenden Status aus dem anfänglichen neuen Status ein, z. B. Runnable. Sobald der Thread die Ausführung abgeschlossen hat, wechselt der Thread in den beendeten Status und der beendete Status kann niemals zurückkehren, sodass die obige Ausnahme ausgelöst wird , das heißt Es heißt, dass es nicht in den Ausgangszustand zurückversetzt werden kann. Die Beschreibung hier ist nicht klar genug. Schauen wir uns den Quellcode an, um es besser zu verstehen. 🎜🎜🎜threadStatus
wird wie folgt kommentiert, was bedeutet, dass der Java-Thread-Status zunächst als 0 (noch nicht gestartet) ausgedrückt wird:🎜rrreee🎜🎜Zweiter Schritt: 🎜Fügen Sie es zur Thread-Gruppe hinzu. Das heißt, der folgende Code:🎜rrreee🎜🎜Schritt 3:🎜Rufen Sie schließlich start0()
diese native Methode auf (nativ bedeutet, dass ihr Code nicht von Java, sondern von C/C++ implementiert wird, insbesondere The Die Implementierung ist im JDK zu sehen, verstehen Sie es einfach), also den folgenden Code: 🎜rrreeeThread
runrun
-Methode von Thread
ungültig und die überschriebene run
-Methode wird ausgeführt. 🎜Zweitens: Übergeben Sie das target
-Objekt (d. h. die Implementierung der Runnable
-Schnittstelle) und führen Sie den ursprünglichen Lauf von <code>Thread aus. code> Die Methode
führt dann die Methode run
des Objekts target
aus. target
对象(即 Runnable
接口的实现),执行 Thread
的原有 run
方法然后接着执行 target
对象的 run
方法。
总结:
run
方法就是一个普通的方法, 上文中直接去执行 run
方法也就是相当于我们执行自己写的普通方法一样,所以它的执行线程就是我们的主线程。run
方法,而是要调用 start
方法,其中可以间接的调用 run
DieVerwandte Lernempfehlungen: 🎜🎜🎜Java-Grundlagen🎜🎜🎜🎜run
-Methode ist eine gewöhnliche Methode, die der Ausführung der gewöhnlichen Methode entspricht, die wir selbst geschrieben haben Die Methode ist dieselbe, daher ist ihr Ausführungsthread unser Hauptthread.Wenn Sie also tatsächlich einen Thread starten möchten, können Sie die Methode
run
nicht direkt aufrufen, sondern müssen die Methodestart
aufrufen, in der Sierun
Methode.
Das obige ist der detaillierte Inhalt vonEin genauerer Blick auf die richtigen und falschen Möglichkeiten, Threads in Java zu starten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!