以下通過兩個實例代碼,比較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方法的內容。
以上內容有誤,歡迎指出。