以下通过两个实例代码,比较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方法的内容。
以上内容有误,欢迎指出。