由于线程在我们操作系统中也是非常宝贵的资源,在实际开发中,我们常常用线程池来重复利用现有的线程来执行任务,避免多次创建和销毁线程,从而降低创建和销毁线程过程中的代价。Java 给我们提供了 Executor 接口来使用线程池,查看其JDK1.8源码,发现其内部封装了Thread t = new Thread()
if (java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) != NULL) { throw_illegal_thread_state = true; } else { // We could also check the stillborn flag to see if this thread was already stopped, but // for historical reasons we let the thread detect that itself when it starts running
// stack size if (os::Linux::supports_variable_stack_size()) { // calculate stack size if it's not specified by caller if (stack_size == 0) { stack_size = os::Linux::default_stack_size(thr_type);
switch (thr_type) { case os::java_thread: // Java threads use ThreadStackSize which default value can be // changed with the flag -Xss assert (JavaThread::stack_size_at_create() > 0, "this should be set"); stack_size = JavaThread::stack_size_at_create(); break; case os::compiler_thread: if (CompilerThreadStackSize > 0) { stack_size = (size_t)(CompilerThreadStackSize * K); break; } // else fall through: // use VMThreadStackSize if CompilerThreadStackSize is not defined case os::vm_thread: case os::pgc_thread: case os::cgc_thread: case os::watcher_thread: if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K); break; } }
stack_size = MAX2(stack_size, os::Linux::min_stack_allowed); pthread_attr_setstacksize(&attr, stack_size); } else { // let pthread_create() pick the default value. }
{ // Serialize thread creation if we are running with fixed stack LinuxThreads boollock= os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack(); if (lock) { os::Linux::createThread_lock()->lock_without_safepoint_check(); }
if (ret != 0) { if (PrintMiscellaneous && (Verbose || WizardMode)) { perror("pthread_create()"); } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; if (lock) os::Linux::createThread_lock()->unlock(); returnfalse; }
// Store pthread info into the OSThread osthread->set_pthread_id(tid);
// Wait until child thread is either initialized or aborted { Monitor* sync_with_child = osthread->startThread_lock(); MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag); while ((state = osthread->get_state()) == ALLOCATED) { sync_with_child->wait(Mutex::_no_safepoint_check_flag); } }
if (lock) { os::Linux::createThread_lock()->unlock(); } }
// Aborted due to thread limit being reached if (state == ZOMBIE) { thread->set_osthread(NULL); delete osthread; returnfalse; }
// The thread is returned suspended (in state INITIALIZED), // and is started higher up in the call chain assert(state == INITIALIZED, "race condition"); returntrue; }
但此时线程才诞生,那是怎么启动的?我们回到JVM_StartThread源码中,Thread::start(native_thread)很明显这行代码就表示启动native_thread = new JavaThread(&thread_entry, sz)创建的线程,我们来继续看看其源码
1 2 3 4 5 6 7 8 9 10 11 12 13
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()) { // 设置线程状态 java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(), java_lang_Thread::RUNNABLE); } os::start_thread(thread); } }
// Thread start routine for all newly created threads staticvoid *java_start(Thread *thread) { // Try to randomize the cache line index of hot stack frames. // This helps when threads of the same stack traces evict each other's // cache lines. The threads can be either from the same JVM instance, or // from different JVM instances. The benefit is especially true for // processors with hyperthreading technology. staticintcounter=0; intpid= os::current_process_id(); alloca(((pid ^ counter++) & 7) * 128);
// non floating stack LinuxThreads needs extra check, see above if (!_thread_safety_check(thread)) { // notify parent thread MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag); osthread->set_state(ZOMBIE); sync->notify_all(); return NULL; }
// thread_id is kernel thread id (similar to Solaris LWP id) osthread->set_thread_id(os::Linux::gettid());
if (UseNUMA) { intlgrp_id= os::numa_get_group_id(); if (lgrp_id != -1) { thread->set_lgrp_id(lgrp_id); } } // initialize signal mask for this thread os::Linux::hotspot_sigmask(thread);
// initialize floating point control register os::Linux::init_thread_fpu_state();
// handshaking with parent thread { MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);
// The first routine called by a new Java thread 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);
// 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); }
JFR_ONLY(Jfr::on_thread_start(this);)
// 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! }
// 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);//JavaThread对象中传入的entry_point为Thread对象的Thread::run方法 }