线程的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方法的内容。

以上内容有误,欢迎指出。

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