Thread.start()让线程启动的方法是什么

发布时间:2021-10-23 16:02:59 作者:iii
来源:亿速云 阅读:126

这篇文章主要讲解了“Thread.start()让线程启动的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Thread.start()让线程启动的方法是什么”吧!

线程启动分析

new Thread(() -> {     // todo }).start();

「咳咳」,Java  的线程创建和启动非常简单,但如果问一个线程是怎么启动起来的往往并不清楚,甚至不知道为什么启动时是调用start(),而不是调用run()方法呢?

「那么」,为了让大家有一个更直观的认知,我们先站在上帝视角。把这段 Java 的线程代码,到 JDK 方法使用,以及 JVM  的相应处理过程,展示给大家,以方便我们后续逐步分析。

Thread.start()让线程启动的方法是什么


图 19-1 线程启动分析

「以上」,就是一个线程启动的整体过程分析,会涉及到如下知识点:

接下来,我们就开始逐步分析每一步源码的执行内容,从而了解线程启动过程。

线程启动过程

1. Thread start UML 图

Thread.start()让线程启动的方法是什么


图 19-2 Thread start UML 图

如图 19-2 是线程的启动过程时序图,整体的链路较长,会涉及到 JVM 的操作。核心源码如下:

  1. Thread.c:https://github.com/unofficial-openjdk/openjdk/blob/jdk/jdk/src/java.base/share/native/libjava/Thread.c

  2. jvm.cpp:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/prims/jvm.cpp

  3. thread.cpp:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/runtime/thread.cpp

  4. os.cpp:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/runtime/os.hpp

  5. os_linux.cpp:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/os/linux/vm/os_linux.cpp

  6. os_windows.cpp:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/os/windows/vm/os_windows.cpp

  7. vmSymbols.hpp:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/classfile/vmSymbols.hpp

2. Java 层面 Thread 启动

2.1 start() 方法

new Thread(() -> {     // todo }).start();  // JDK 源码 public synchronized void start() {      if (threadStatus != 0)         throw new IllegalThreadStateException();      group.add(this);     boolean started = false;     try {         start0();         started = true;     } finally {         try {             if (!started) {                 group.threadStartFailed(this);             }         } catch (Throwable ignore) {}     } }

2.2 start0() 本地方法

// 本地方法 start0 private native void start0();  // 注册本地方法 public class Thread implements Runnable {     /* Make sure registerNatives is the first thing <clinit> does. */     private static native void registerNatives();     static {         registerNatives();     }     // ... }

「registerNatives」,本地方法定义在 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},     {"interrupt0",       "()V",        (void *)&JVM_Interrupt},     {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},     {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},     {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},     {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName}, };

3. JVM 创建线程

3.1  JVM_StartThread

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/prims/jvm.cpp

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))   JVMWrapper("JVM_StartThread");   JavaThread *native_thread = NULL;      // 创建线程   native_thread = new JavaThread(&thread_entry, sz);   // 启动线程   Thread::start(native_thread);  JVM_END

这部分代码比较多,但核心内容主要是创建线程和启动线程,另外 &thread_entry也是一个方法,如下:

「thread_entry,线程入口」

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); }

「重点」,在创建线程引入这个线程入口的方法时,thread_entry 中包括了 Java 的回调函数  JavaCalls::call_virtual。这个回调函数会由 JVM 调用。

「vmSymbols::run_method_name()」,就是那个被回调的方法,源码如下:

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/classfile/vmSymbols.hpp

#define VM_SYMBOLS_DO(template, do_alias) template(run_method_name, "run")

这个 run 就是我们的 Java 程序中会被调用的 run 方法。接下来我们继续按照代码执行链路,寻找到这个被回调的方法在什么时候调用的。

3.2 JavaThread

native_thread = new JavaThread(&thread_entry, sz);

接下来,我们继续看 JavaThread 的源码执行内容。

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/runtime/thread.cpp

JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :   Thread() #if INCLUDE_ALL_GCS   , _satb_mark_queue(&_satb_mark_queue_set),   _dirty_card_queue(&_dirty_card_queue_set) #endif // INCLUDE_ALL_GCS {   if (TraceThreadEvents) {     tty->print_cr("creating thread %p", this);   }   initialize();   _jni_attach_state = _not_attaching_via_jni;   set_entry_point(entry_point);   // Create the native thread itself.   // %note runtime_23   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); }

3.3 os::create_thread

「源码」:

os_linux.cpp:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/os/linux/vm/os_linux.cpp

os_windows.cpp:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/os/windows/vm/os_windows.cpp

众所周知,JVM 是个啥!,所以它的 OS 服务实现,Liunx 还有 Windows 等,都会实现线程的创建逻辑。这有点像适配器模式

「os_linux -> os::create_thread」

bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {   assert(thread->osthread() == NULL, "caller responsible");    // Allocate the OSThread object   OSThread* osthread = new OSThread(NULL, NULL);   // Initial state is ALLOCATED but not INITIALIZED   osthread->set_state(ALLOCATED);      pthread_t tid;   int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);    return true; }

3.4  java_start

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/os/linux/vm/os_linux.cpp

static void *java_start(Thread *thread) {    // 线程ID   int pid = os::current_process_id();    // 设置线程   ThreadLocalStorage::set_thread(thread);    // 设置线程状态:INITIALIZED 初始化完成   osthread->set_state(INITIALIZED);      // 唤醒所有线程   sync->notify_all();   // 循环,初始化状态,则一致等待 wait  while (osthread->get_state() == INITIALIZED) {     sync->wait(Mutex::_no_safepoint_check_flag);  }    // 等待唤醒后,执行 run 方法   thread->run();    return 0; }

4. JVM 启动线程

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))   JVMWrapper("JVM_StartThread");   JavaThread *native_thread = NULL;      // 创建线程   native_thread = new JavaThread(&thread_entry, sz);   // 启动线程   Thread::start(native_thread);  JVM_END

JVM_StartThread 中有两步,创建(new  JavaThread)、启动(Thread::start)。创建的过程聊完了,接下来我们聊启动。

4.1  Thread::start

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/runtime/thread.cpp

void Thread::start(Thread* thread) {   trace("start", thread);    if (!DisableStartThread) {     if (thread->is_Java_thread()) {       java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),                                           java_lang_Thread::RUNNABLE);     }     // 不同的 OS 会有不同的启动代码逻辑     os::start_thread(thread);   } }

4.2  os::start_thread(thread)

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/runtime/os.hpp

void os::start_thread(Thread* thread) {   // guard suspend/resume   MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);   OSThread* osthread = thread->osthread();   osthread->set_state(RUNNABLE);   pd_start_thread(thread); }

osthread->set_state(RUNNABLE),设置线程状态  RUNNABLEpd_start_thread(thread),启动线程,这个就由各个 OS  实现类,实现各自系统的启动方法了。比如,windows系统和Linux系统的代码是完全不同的。

4.3  pd_start_thread(thread)

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/os/linux/vm/os_linux.cpp

void os::pd_start_thread(Thread* thread) {   OSThread * osthread = thread->osthread();   assert(osthread->get_state() != INITIALIZED, "just checking");   Monitor* sync_with_child = osthread->startThread_lock();   MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);   sync_with_child->notify(); }

这部分代码 notify() 最关键,它可以唤醒线程。

线程唤醒后,3.4 中的 thread->run(); 就可以继续执行了。

5. JVM 线程回调

5.1  thread->run()[JavaThread::run()]

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/runtime/thread.cpp

// The first routine called by a new Java thread void JavaThread::run() {   // ... 初始化线程操作      thread_main_inner(); }

os_linux.cpp 类中的 java_start 里的 thread->run(),最终调用的就是 thread.cpp 的  JavaThread::run() 方法。

这部分还需要继续往下看,thread_main_inner(); 方法。

5.2  thread_main_inner

「源码」:https://github.com/JetBrains/jdk8u_hotspot/blob/master/src/share/vm/runtime/thread.cpp

void JavaThread::thread_main_inner() {    if (!this->has_pending_exception() &&       !java_lang_Thread::is_stillborn(this->threadObj())) {     {       ResourceMark rm(this);       this->set_native_thread_name(this->get_thread_name());     }     HandleMark hm(this);     this->entry_point()(this, this);   }    DTRACE_THREAD_PROBE(stop, this);    this->exit(false);   delete this; }

总结

感谢各位的阅读,以上就是“Thread.start()让线程启动的方法是什么”的内容了,经过本文的学习后,相信大家对Thread.start()让线程启动的方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. Atom如何利用Markdown存放图片
  2. C# 中怎么调用Thread.Start()方法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

thread.start() jvm

上一篇:如何进行JConsole和JVisualJVM的入门

下一篇:怎样了解JVM内存模型

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》