Skip to content

Java 线程模型

1.线程模型

  1. 用户态线程 (User-Level Thread)

jdk 1.0 的早期实现,完全由 JVM 在用户空间管理

  • 轻量级:创建和销毁成本低,线程切换、调度开销小、速度快
  • 不可见的阻塞:一个用户线程阻塞会导致整个进程阻塞(内核视角只有单线程)
  1. 内核态线程 (Kernel-Level Thread)

Java 1.2 引入,HotSpot 采用此模型,Java 线程 1:1 映射到内核线程,由操作系统内核直接管理

  • 性能:线程切换、调度需要内核参与,涉及上下文切换,开销大
  • 并行性:多核 CPU 可真正并行执行
  1. 混合模型 (协程)

jdk 21 提供虚拟线程(Virtual Threads),本质上是协程的一种实现

  • 本质:大量的用户态线程(虚拟线程)映射到少量的载体线程(ForkJoinPool内核线程)
  • 优势:兼容现有 Thread API,无需关注协程底层即可适应高并发场景,避免上下文切换开销
  • 场景:适合 I/O 密集型场景,例如网络服务、数据库访问等

2. JVM 创建 Native Thread 的流程

当调用 new Thread().start() 时:

  • JAVA 创建一个 Thread 对象,初始化栈大小、优先级等参数
  • JVM 内部检查线程参数 (如 -Xss 栈大小),调用 pthread_create (Linux) 或 CreateThread (Windows) 等操作系统 API 创建线程
  • 新创建的 Native Thread 执行入口函数 (如 hotsopt/src/os/linux/vm/os_linux.cpp 中的 java_start 函数), 初始化线程的 栈帧程序计数器寄存器状态,并关联 Java 层的 Thread 对象
  • Native Thread 跳转到 Java Threadrun() 方法的机器码入口,开始执行用户代码

3. Java 线程与 Native Thread 的映射细节

线程本地存储

  • 通过 ThraedLocal 存储的变量,保存在 Java Thread 对象内部(通过 ThreadLocalMap 维护)
  • Native Thread 的 TLS 中存储了 JVM 内部线程结构指针,用于快速定位 Java 层状态

线程中断

  • 当调用 Thread.interrupt() 并不会直接操作 Native Thread,而是设置 Thread 对象的中断状态位
  • 如果 Native Thread 因 wait()sleep() 等阻塞时,JVM 注入中断信号(如 Linux 的SIGINT)唤醒线程,抛出 InterruptedException

JNI线程附加

  • 当 Native 代码通过 JNI 调用 AttachCurrentThread(), JVM 会将当前 Native Thread 绑定到新的 Java Thread 对象
  • 该线程会被 JVM 视为活动的 Java 线程,直到显示调用 DetachCurrentThread()

4. 性能与限制

  • 每个 Native Thread 需要独立的内核栈 (通常 1~8 MB)和上下文切换成本
  • Native Thread 数量受操作系统的线程数上限限制

虚拟线程

JDK19+ 引入了虚拟线程,多由 JVM 管理,多个虚拟线程复用一个 Native Thread,创建和调度开销都很小

Java 线程生命周期

线程生命周期.png