首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 線程底層原理深度解析:從 OS 線程模型到 run() 執行全流程

     編輯:Java 綜合教學

導語:new Thread() 之後發生了什麼?

我們都知道 new Thread().start() 能啟動線程,但 run() 方法究竟是如何被調用執行的?本文將從操作系統線程模型切入,層層剖析 Java 線程與本地線程的映射關係,深入 JDK 源碼追蹤 start() 到 run() 的完整調用鏈路。

一、作業系統線程模型:三種實現方式

1. 內核線程實現 (1:1 模型)

內核線程模型圖解
KLT 由內核直接調度,LWP 作為高級接口與 KLT 1:1 對應
  • 優勢:每個 LWP 獨立調度,單線程阻塞不影響進程繼續運行
  • 劣勢:系統調用開銷大,受限於內核資源

2. 用戶線程實現 (N:1 模型)

用戶線程模型圖解
完全在用戶空間管理,內核不可感知線程存在
  • 優勢:線程操作無需內核支援,創建切換極快
  • 劣勢:單線程阻塞導致整個進程阻塞,無法利用多核優勢

3. 混合實現 (N:M 模型)

混合線程模型圖解
用戶線程與 LWP 通過 N:M 映射,兼具並發規模與調度能力
  • 用戶線程創建/銷毀/切換廉價,支持大規模並發
  • LWP 作為橋樑提供調度與處理器映射
  • 系統調用通過 LWP 完成,降低進程完全阻塞風險

二、Java 線程模型演進

  • JDK 1.2 之前:基於用戶線程(綠色線程)實現
  • JDK 1.2 起:採用操作系統原生線程模型
  • 現代 JDK:線程映射取決於 OS 支持模型,Sun JDK Windows/Linux 均採用 1:1 模型,即一條 Java 線程映射一條 LWP

三、Java 線程創建與啟動機制

創建方式統一入口

Thread 創建方式類圖
繼承 Thread 或實現 Runnable,最終都重寫 run(),但啟動均調用 start()

run() 本質是一個回調函數,與普通方法無異;start() 則負責啟動本地線程並安排 run() 執行。

核心實現:JNI 層面的 start0()

// Thread.java
private native void start0();

// 類加載時靜態塊註冊本地方法
static {
    registerNatives();
}
private static native void registerNatives();

registerNatives() 在 Thread.c 中實現,將 start0 映射到 JVM_StartThread:

// Thread.c
static JNINativeMethod methods[] = {
    {"start0", "()V", (void *)&JVM_StartThread},
    {"stop0", "(" OBJ ")V", (void *)&JVM_StopThread},
    // ... 其他本地方法
};

JVM 層面:創建本地線程並調用 run()

// jvm.cpp
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) {
    // 創建平台相關的本地線程
    JavaThread* native_thread = new JavaThread(&thread_entry, sz);
    // ...
}

線程入口函數 thread_entry 通過 JNI 調用 Java 線程的 run():

static void thread_entry(JavaThread* thread, TRAPS) {
    HandleMark hm(THREAD);
    Handle obj(THREAD, thread->threadObj());
    JavaValue result(T_VOID);
    // 關鍵:調用 run 方法
    JavaCalls::call_virtual(&result, obj,
        KlassHandle(THREAD, SystemDictionary::Thread_klass()),
        vmSymbolHandles::run_method_name(),  // "run"
        vmSymbolHandles::void_method_signature(),
        THREAD);
}

方法名在 vmSymbols.hpp 定義:

template(run_method_name, "run")

四、完整調用關係圖譜

Java 線程創建調用關係圖
start() → start0() → JVM_StartThread() → thread_entry() → run()

總結:Java 線程啟動本質是創建本地線程,由 JVM 通過 JNI 回調執行 Java 層的 run() 方法。理解這一機制,有助於深入掌握線程生命周期、上下文切換及性能調優的底層邏輯。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved