JUC プログラミング - スレッド開始メソッドと基礎となるソース コード

小さな栗 1個

スレッドの小さな栗を書くだけです:

public class ThreadTest extends Thread {
    
    
    @Override
    public void run() {
    
    
        System.out.println("In run");
    }
    public static void main(String []argv) {
    
    
        (new ThreadTest()).start();
    }
}

2 start()メソッドのソースコード解析

2.1 start() ソースコード

Java start() メソッドのソース コードを表示します。

    public synchronized void start() {
    
    
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
    
    
        	// 主要是这个函数
            start0();
            // started=true表示线程运行成功
            started = true;
        } finally {
    
    
            try {
    
    
                if (!started) {
    
    
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
    
    
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

2.2 start0() メソッド

	// start()方法调用start0()方法
	// native方法 调用底层C++方法
    private native void start0();

2.3 基礎となる C++ ソース コード

さらに低レベルの C++ コード:

  • thread.c (コードの場所: openJDK\src\share\native\java\lang)
  • jvm.cpp (コードの場所: openIDK\hotspot\src\share\vm\prims)
  • thread.cpp (コードの場所: openJDK\hotspot\src\share\vm\runtime)

コード - OpenJDK ソース URL: http://openjdk.java.net/

2.3.1 thread.c

Thread.java は thread.c ソース コードに対応します

.c のソース コードから、start0() が実際には JVM_StartThread=>find jvm.cpp であることがわかります。

#include "jni.h"
#include "jvm.h"

#include "java_lang_Thread.h"

#define THD "Ljava/lang/Thread;"
#define OBJ "Ljava/lang/Object;"
#define STE "Ljava/lang/StackTraceElement;"
#define STR "Ljava/lang/String;"

#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))

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

#undef THD
#undef OBJ
#undef STE
#undef STR

JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{
    
    
    (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}

2.3.2 jvm.cpp

jvm.cpp のソース コードの一部:
主に、JVM_StartThread メソッドの最初の行と Thread::start(native_thread) の最後の行がスレッドを開始することがわかります。

// JVM_StartThread方法
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);
      }
    }
  }

  if (throw_illegal_thread_state) {
    
    
    THROW(vmSymbols::java_lang_IllegalThreadStateException());
  }

  assert(native_thread != NULL, "Starting null thread?");

  if (native_thread->osthread() == NULL) {
    
    
    // No one should hold a reference to the 'native_thread'.
    delete native_thread;
    if (JvmtiExport::should_post_resource_exhausted()) {
    
    
      JvmtiExport::post_resource_exhausted(
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,
        "unable to create new native thread");
    }
    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),
              "unable to create new native thread");
  }

#if INCLUDE_JFR
  if (JfrRecorder::is_recording() && EventThreadStart::is_enabled() &&
      EventThreadStart::is_stacktrace_enabled()) {
    
    
    JfrThreadLocal* tl = native_thread->jfr_thread_local();
    // skip Thread.start() and Thread.start0()
    tl->set_cached_stack_trace_id(JfrStackTraceRepository::record(thread, 2));
  }
#endif

  // 启动线程
  Thread::start(native_thread);

2.3.3 thread.cpp ソースコード

最後に、start メソッドがオペレーティング システム レベルで開始されます。

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);
    }
    // 最终是操作系统级别提高了start方法
    os::start_thread(thread);
  }
}

Guess you like

Origin blog.csdn.net/COINVK/article/details/130057577