天天看点

Thread中的start和run方法的区别

Thread中start和run方法的区别

由打印结果可以知道,当执行

start()

方法时,会创建一个新的线程

Thread-0

public class ThreadTest {
    private static void attack(){
        System.out.println("fight");
        System.out.println("current thread: "+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        Thread t = new Thread(){
            @Override
            public void run(){
                attack();
            }
        };
        System.out.println("current main thread: "+Thread.currentThread().getName());
        // t.run();
        t.start();
    }
}
           

打印结果

current main thread: main
fight
current thread: Thread-0
           

如果

t.start();

换成

t.run();

,可以看出

run()

方法没有创建新的线程,仍然是

main

线程

current main thread: main
fight
current thread: main
           

查看start()源码

public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then

           

其中重要的是

start0()

方法,进入查看源码。

发现是native方法,通过下方链接可查看源码

http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e36dcb7d407e/src/share/native/java/lang/Thread.c
           

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},
    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
    {"resume0",          "()V",        (void *)&JVM_ResumeThread},
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    {"yield",            "()V",        (void *)&JVM_Yield},
    {"sleep",            "(J)V",       (void *)&JVM_Sleep},
    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
    {"countStackFrames", "()I",        (void *)&JVM_CountStackFrames},
    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
    {"isInterrupted",    "(Z)Z",       (void *)&JVM_IsInterrupted},
    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
    {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};

#undef THD
#undef OBJ
#undef STE
#undef STR

JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}
           

可以看到

{"start0", "()V", (void *)&JVM_StartThread},

,即

start0

使用

jvm.h

中的JVM_StartThread方法,我们去查看

jvm.h

的代码。通过下方链接可查看

http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/cf6e3496e19a/src/share/vm/prims/jvm.cpp
           
Thread中的start和run方法的区别

顺着方法往下看

Thread中的start和run方法的区别

可以看到new了一个JavaThread,其中传递了两个参数

thread_entry

sz

Thread中的start和run方法的区别

可以看到,JavaThread会执行

run

方法

总结

调用流程

Thread中的start和run方法的区别

小结

Thread中的start和run方法的区别