Java Thread中start方法和run方法的关系
- 仔细看run方法可以知道,run方法仅仅是Thread中的一个成员方法,那么它是如何与线程的运行挂钩呢?
- 线程开启之后为什么要执行run方法呢?
要解释上面的问题首先要知道Java开启一个线程的流程
1、API层级
new Thread().start()
2、JDK层级
在Thread中,会导入本地方法库
public class Thread implements Runnable {
/* Make sure registerNatives is the first thing does. */
private static native void registerNatives();
static {
registerNatives();
}
而registerNatives方法在JDK源码中的体现在 openjdk/src/share/native/java/lang/Thread.c
其中映射了很多的本地方法,主要分析start方法
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},
};
JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}
3、JVM层
JVM_StartThread方法对应着hostspot/src/share/vm/prims/jvm.cpp
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
JVMWrapper("JVM_StartThread");
// ... 栈大小,默认是1M
jlong size = java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
size_t sz = size > 0 ? (size_t) size : 0;
native_thread = new JavaThread(&thread_entry, sz);
// ...
4、从这里可以看出在JVM_StartThread中真正创建出了与JVM平台相关的本地线程
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);
}
5、这个run_method_name就是指定线程运行的回调方法
hostspot/src/share/vm/classfile/vmSymbols.hpp
template(run_method_name, "run") \
到这里是不是就明白了为什么线程启动后会调用run方法。
关于线程是如何创建的逻辑在 /runtime/Thread.cpp
中
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
Thread(){
os::ThreadType thr_type = os::java_thread;
thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread : os::java_thread;
os::create_thread(this, thr_type, stack_sz);
}