原創轉載請注明出處:https://www.cnblogs.com/agilestyle/p/11421515.html
start
用start方法來啟動線程,真正實現了多線程運行,這時無需等待run方法體代碼執行完畢而直接繼續執行下面的代碼。通過調用Thread類的start()方法來啟動一個線程,這時此線程處於就緒(可運行)狀態,並沒有運行,一旦得到cpu時間片,就開始執行run()方法,這里方法run()稱為線程體,它包含了要執行的這個線程的內容,run方法運行結束,此線程隨即終止。
start方法源碼示例

一個 Java 線程的創建本質上就對應了一個本地線程(native thread)的創建,兩者是一一對應的。
關鍵問題是:本地線程執行的應該是本地代碼,而 Java 線程提供的線程函數(run)是 Java 方法,編譯出的是 Java 字節碼。
所以, Java 線程其實提供了一個統一的線程函數,該線程函數通過 Java 虛擬機調用 Java 線程方法 , 這是通過 Java 本地方法 start0 調用來實現的。
也就是新創建的線程啟動調用native start0方法,而這些native方法的注冊是在Thread對象初始化的時候完成的

Thread 類有個 registerNatives 本地方法,該方法主要的作用就是注冊一些本地方法供 Thread 類使用,如 start0(),stop0() 等等,可以說,所有操作本地線程的本地方法都是由它注冊的。
這個方法放在一個 static 語句塊中,當該類被加載到 JVM 中的時候,它就會被調用,進而注冊相應的本地方法。(查看本地方法的源碼需要前往 http://jdk.java.net/java-se-ri/8 下載openjdk的源代碼)
而本地方法 registerNatives 是定義在 Thread.c 文件中的。Thread.c 是個很小的文件,它定義了各個操作系統平台都要用到的關於線程的公用數據和操作,如下:

可以看出 Java 線程調用 start->start0 的方法,實際上會調用到 JVM_StartThread 方法,而 JVM_StartThread 最終調用的是 Java 線程的 run 方法。
在 jvm.cpp 中,有如下代碼段:

這里 JVM_ENTRY 是一個宏,用來定義 JVM_StartThread 函數,可以看到函數內創建了真正的平台相關的本地線程,其線程函數是 thread_entry,如下:

可以看到調用了 vmSymbols::run_method_name 方法,而 run_method_name 是在 vmSymbols.hpp 用宏定義的:

run
run()方法只是類的一個普通方法而已,如果直接調用Run方法,程序中依然只有主線程這一個線程,其程序執行路徑還是只有一條,還是要順序執行,還是要等待run方法體執行完畢后才可繼續執行下面的代碼,這樣就沒有達到寫線程的目的。
run方法源碼示例

分別測試start和run
1 package org.fool.test.thread; 2 3 public class ThreadTest { 4 public static void main(String[] args) { 5 Thread thread = new Thread(new Runnable() { 6 @Override 7 public void run() { 8 System.out.println(Thread.currentThread().getName() + " invoked..."); 9 } 10 }); 11 thread.start(); 12 //thread.run(); 13 } 14 }
先運行thread.start()
Thread-0 invoked...
注釋調thread.start()方法,運行thread.run()
main invoked...
Summary
start方法可啟動多線程
run方法只是thread的一個普通方法調用,還是在主線程里執行,是不會開啟多線程的
