線程的start()和run()方法的區別

以下通過兩個實例代碼,比較start()和run()方法的區別:

示例一:新建一個線程並調用start()方法

public class StartAndRun {

    public static void main(String[] args) {
        Thread thread = new Thread(new Runner(), "thread-1");
        thread.start();
    }

    private static class Runner implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is running");
        }
    }
}

運行結果:thread-1 is running,main線程啓動了一個新的線程thread-1執行了run()方法的內容。線程在初始化完成後,調用start()啓動線程,但是該線程什麼時候執行需要由JVM來決定。

實例二:調用run()方法

public class StartAndRun {

    public static void main(String[] args) {
        Thread thread = new Thread(new Runner(), "thread-1");
        thread.run();
    }

    private static class Runner implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " is running");
        }
    }
}

運行結果:main is running

總結:調用start()方法會創建一個子線程執行,而通過run()方法執行只是相當於一個普通的方法調用。

2.start方法中是怎麼創建子線程的,又是怎麼通過start()方法執行run()方法的?

JDK中通過start0中創建子線程,start0是一個native方法,表示該方法是用系統底層語言實現的。

public synchronized void start() {
        try {
            start0();
            started = true;
            ...
private native void start0();

可以通過查看JDK的源碼,查看start0的具體實現,
http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/beb15266ba1a/src/share/native/java/lang/Thread.c

#include "jni.h"
#include "jvm.h"
#include "java_lang_Thread.h"
#define THD "Ljava/lang/Thread;"
#define OBJ "Ljava/lang/Object;"
#define STE "Ljava/lang/StackTraceElement;"
#define STR "Ljava/lang/String;"
#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
static JNINativeMethod methods[] = {
    {"start0",           "()V",        (void *)&JVM_StartThread},

start0調用的JVM_StartThread方法,該方法在jvm.h中

jvm.h的源碼
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/b4fd7e078c54/src/share/vm/prims/jvm.cpp

native_thread = new JavaThread(&thread_entry, sz);
static void thread_entry(JavaThread* thread, TRAPS) {
  HandleMark hm(THREAD);
  Handle obj(THREAD, thread->threadObj());
  JavaValue result(T_VOID);
  JavaCalls::call_virtual(&result,
                          obj,
                          KlassHandle(THREAD, SystemDictionary::Thread_klass()),
                          vmSymbols::run_method_name(),
                          vmSymbols::void_method_signature(),
                          THREAD);
}

筆者對源碼的理解也不深刻,大概可以推斷出JVM通過 new JavaThread(&thread_entry, sz)創建一個新的線程,通過call_virtual的定義執行run方法的內容。

以上內容有誤,歡迎指出。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章