跳转至

new Thread().start() 创建一个线程时,操作系统层面发生了什么?

题外话:这个问题是今年秋招作业帮出过的一道题,面试官问的还挺有水平的,其实这个问题考察的就是虚拟线程相关的问题,或者说是虚拟线程出来之前的平台线程的实现原理。因为涉及到一点操作系统底层了,所以不好回答。据说完全答对的几乎没有。

典型回答

new Thread().start()这个方法创建并启动线程的话,用的是平台线程,Java早期(JDK 21之前的线程,以及JDK 21之后不用虚拟线程的时候)的线程的是实现是靠操作系统内核线程来实现的,并且Java线程和OS内核线程之间是一对一的关系。

5_✅JDK21 中的虚拟线程是怎么回事?

所以,操作系统层面,**new Thread()**主要是进行OS线程的创建,主要分以下四步:

分配内核线程

  • 内核为新线程创建线程控制块(TCB),包含:
    • 线程 ID(TID)
    • 寄存器状态(PC、SP 等)
    • 调度优先级
    • 所属进程(共享地址空间、文件描述符等)

分配栈空间

  • 用户态栈:默认大小由 JVM 控制(可通过 -Xss 设置,如 -Xss1m)。
    • 例如:Linux 上默认可能是 1MB(但实际是虚拟内存,按需分配物理页)。
  • 内核栈:每个线程在内核中也有自己的栈(通常 8–16KB),用于系统调用。

设置初始上下文

  • 程序计数器(PC)指向 thread_entry_point(JVM 的 C 入口函数)。
  • 栈指针(SP)指向新分配的用户栈顶部。

加入调度器就绪队列

  • 线程状态变为 RUNNABLE(可运行)。
  • 由操作系统的调度器(如 Linux 的 CFS)决定何时在 CPU 上执行。

**.start**方法的调用,则是线程的真正执行了

  • 新线程拿到CPU时间片
  • 执行 thread_entry_point → 初始化 JNI → 调用 Thread.run() → 最终执行你传入的 Runnable.run()