thread start() 源码解析

我们步步深入start()

  1. 进入到start()方法的源码
    在这里插入图片描述
  2. 在这里线程会加入到线程分组,然后执行start0(),thread start() 源码解析_第1张图片
  3. 从图片可以看书start0 是一个本地的方法,start0()这个方法是在Thread的静态块中来注册的,其作用就是注册一些本地方法提供给Thread类来使用,比如start0()、isAlive()… ,具体方法在一个C的文件中Thread.c,其定义了各个操作系统平台要用的关于线程的公共数据和操作,具体定义了很多的方法都是各个操作系统能公共调用的,也就是线程在构建时候,会将这些方法注册上去,

thread start() 源码解析_第2张图片
thread start() 源码解析_第3张图片

  1. start0() 会调用 JVM_StartThread 这个方法,JVM层面去启动一个线程,我们需要下载hotspot的源码才能找到.我们找到: jvm.cpp这个文件
    JVM_ENTRY是用来定义 JVM_StartThread函数的,在这个函数里面创建了一个真正和平台有关的本地线程
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_StartThread");
...
native_thread = new JavaThread(&thread_entry, sz);
  1. hotspot的源码中 thread.cpp文件中1558行的位置
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);
  _safepoint_visible = false;
 
}

这个方法有两个参数,第一个是函数名称,线程创建成功之后会根据这个函数名称调用对应的函数;第二个是当前进程内已经有的线程数量。最后我们重点关注与一下 os::create_thread,实际就是调用平台创建线程的方法来创建线程。

6.其中start方法中会有一个函数调用,os::start_thread(thread);,调用平台启动线程的方法,最终会调用Thread.cpp文件中的JavaThread::run()方法

void Thread::start(Thread* thread) {
  trace("start", thread);
  // Start is different from resume in that its safety is guaranteed by context or
  // being called from a Java method synchronized on the Thread object.
  if (!DisableStartThread) {
    if (thread->is_Java_thread()) {
      // Initialize the thread state to RUNNABLE before starting this thread.
      // Can not set it after the thread started because we do not know the
      // exact thread state at that time. It could be in MONITOR_WAIT or
      // in SLEEPING or some other state.
      java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),
                                          java_lang_Thread::RUNNABLE);
    }
    os::start_thread(thread);
  }
}
  1. 在其中JavaThread会进行一系列的初始化操作,最后有一个方法 thread_main_inner
void JavaThread::run() {
  // initialize thread-local alloc buffer related fields
  this->initialize_tlab();
  // used to test validitity of stack trace backs
  this->record_base_of_stack_pointer();
  // Record real stack base and size.
  this->record_stack_base_and_size();
  // Initialize thread local storage; set before calling MutexLocker
  this->initialize_thread_local_storage();
  this->create_stack_guard_pages();
  this->cache_global_variables();
  // Thread is now sufficient initialized to be handled by the safepoint code as being
  // in the VM. Change thread state from _thread_new to _thread_in_vm
  ThreadStateTransition::transition_and_fence(this, _thread_new, _thread_in_vm);
  assert(JavaThread::current() == this, "sanity check");
  assert(!Thread::current()->owns_locks(), "sanity check");
  DTRACE_THREAD_PROBE(start, this);
  // This operation might block. We call that after all safepoint checks for a new thread has
  // been completed.
  this->set_active_handles(JNIHandleBlock::allocate_block());
  if (JvmtiExport::should_post_thread_life()) {
    JvmtiExport::post_thread_start(this);
  }
  EventThreadStart event;
  if (event.should_commit()) {
     event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj()));
     event.commit();
  }
  // We call another function to do the rest so we are sure that the stack addresses used
  // from there will be lower than the stack base just computed
  thread_main_inner();
  // Note, thread is no longer valid at this point!
}
  1. thread_main_inner 中,找到核心的代码块 this->entry_point()(this,this), 在第四部中native_thread=newJavaThread(&thread_entry,sz); 的时候传递了一个threadentry函数
void JavaThread::thread_main_inner() {
  assert(JavaThread::current() == this, "sanity check");
  assert(this->threadObj() != NULL, "just checking");
  // Execute thread entry point unless this thread has a pending exception
  // or has been stopped before starting.
  // Note: Due to JVM_StopThread we can have pending exceptions already!
  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;
}
  1. 我们找到thread_entry函数,找到vmSymbols::run_method_name()这个调用,通过回调方法调用Java线程中定义的run方法,让我们来看看, run_method_name是一个宏定义,在vmSymbols.hpp文件中可以找到
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);
}
  1. 找到VM_SYMBOLS_DO 函数,我们可以看到,其对应的就是一个,方法,
#define VM_SYMBOLS_DO(template, do_alias)    
...
template(run_method_name, "run")  
...

总结全文

其大概意思就是,Java里面创建线程之后,必须要调用start方法才能创建一个线程,该方法会通过虚拟机启动一个本地线程,本地线程的创建会调用当前系统去创建线程的方法进行创建线程,并且线程被执行的时候会回调 run方法进行业务逻辑的处理,大概意思就是,系统给你留了一个接口,你要去用这个接口调用你的run 方法,该线程提供给你一系列的操作

你可能感兴趣的:(高并发)