先上結論:run只是Thread裡面的一個普通方法,start是啟動線程的方法。何以見得呢?可以執行下麵的代碼看看run和start的區別: 執行結果: 由此可以看到子線程是由start來啟動的,裡面調用了run,所以列印出來的是子線程的name。 另外也可以從start方法的底層代碼看到,首先進入 ...
先上結論:run只是Thread裡面的一個普通方法,start是啟動線程的方法。何以見得呢?可以執行下麵的代碼看看run和start的區別:
package com.basic.thread; /** * @author zhangxingrui * @create 2019-02-16 20:12 **/ public class TestRunAndStart { private static void sayHello(){ System.out.println("hello, world"); } public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { sayHello(); System.out.println("Current thread: " + Thread.currentThread().getName()); } }); thread.run(); thread.start(); } }
執行結果:
由此可以看到子線程是由start來啟動的,裡面調用了run,所以列印出來的是子線程的name。
另外也可以從start方法的底層代碼看到,首先進入start方法裡面
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(); 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 */ } } }
裡面調用了start0,繼續跟進
private native void start0();
哦,這裡就調了native方法了,再往下我們就看不到了。但是可以去openjdk的源碼裡面去看一下,我用的是jdk8。
去openjdk看源碼
https://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/f0b93fbd8cf8/src/share/native/java/lang/Thread.c
這裡調用了JVM_StartThread,在jvm.h裡面
繼續進入
https://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/76a9c9cf14f1/src/share/vm/prims/jvm.cpp
重點看最下麵的語句native_thread = new JavaThread(&thread_entry, sz),好,new JavaThread的時候傳入了thread_entry,我們再去
看一下啊thread_entry是什麼:
在thread_entry這個函數裡面調用call_virtual方法,重點是它傳入的參數run_method_name,從這裡我們就知道了,噢,
原來start最終會在新線程裡面調用run方法。