前言:Java创建线程,说白了就是创建一个linux的内核线程, 所以Java线程就是linux的内核线程,线程的管理基本上也就是 *** 作系统在进行管理。
那么java是如何从语言层面去让linux内核创建一个线程并让其运行,甚至控制其运行的优先级的?
一、浅层次的,对于我们开发人员来说, 想要启动一个Java线程,主要有两种方法,第一种可以实现一个继承自Thread的子类,重写run();第二种可以实现一个Runnable,交给Thread执行。
然后 执行Thread.start() 才能真正的启动一个异步线程进行工作。
二、深层次的,我们通过追踪start()方法会发现,线程最终是调用一个native的start0()方法,所以想知道java如何启动一个线程,必须去看start0()是如何实现的。
Thread.c 中定义了java方法绑定的一些方法, Thread.c 中的一段定义 如下:
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},
};
从上面我们能看到,start0绑定的方法为:JVM_StartThread,所以我们需要继续看JVM_StartThread方法。
JVM_StartThread定义在jvm.cpp中(.cpp是c++文件的后缀名,start0方法和C++的JVM_StartThread是通过JNI进行 方法的映射 , 将native方法和真正的实现方法进行绑定。
):
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
JVMWrapper("JVM_StartThread");
JavaThread *native_thread = NULL;
bool throw_illegal_thread_state = false;
{
MutexLocker mu(Threads_lock);
if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) {
throw_illegal_thread_state = true;
} else {
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);
if (native_thread->osthread() != NULL) {
native_thread->prepare(jthread);
}
}
}
......
Thread::start(native_thread);
JVM_END
如上,我们看到两段关键的代码,分别是在C++中创建线程和启动线程:
1、native_thread = new JavaThread(&thread_entry, sz); //启动线程
2、Thread::start(native_thread);//让线程运行
上面的new JavaThread(&thread_entry, sz)看起来还不是最终的创建线程方法,我们再进去看下里面的方法:
JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
Thread()
{
initialize();
_jni_attach_state = _not_attaching_via_jni;
set_entry_point(entry_point);
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);//创建内核线程
}
终于找到了, 最后一句os::create_thread(this, thr_type, stack_sz) 便开始真正的创建Java线程对应的内核线程。
其实,也不是最终创建内核线程的方法,我们继续看下这个方法是怎么写的:
bool os::create_thread(Thread* thread, ThreadType thr_type,
size_t req_stack_size) {
......
pthread_t tid;
int ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread);//创建线程
......
return true;
}
上面这个方法主要就是利用pthread_create()来创建线程 ,其中第三个参数thread_native_entry便是新起的线程运行的初始地址,最后,通过调用Thread::start(native_thread);
启动线程
到这里Java线程就已经真正的运行起来了,总结下上面的过程:
1:调用Java线程start()方法,通过jni方式,调用到JVM层。
2:JVM通过pthread_create()创建一个系统内核线程,并指定内核线程的初始运行地址,即一个方法指针。
3:在内核线程的初始运行方法中,利用JavaCalls模块,调用java线程的run()方法,开始java级别的线程执行。
参考:
JVM之Java线程启动流程
JNI详解------完整Demo
JVM方法执行的来龙去脉
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)