当前位置: 首页 > news >正文

深度剖析:在 Java 里 new Thread(),底层到底发生了什么?

深度剖析:在 Java 里new Thread(),底层到底发生了什么?

在日常的业务开发中,我们对new Thread().start()这行代码再熟悉不过了。但你是否曾停下来思考过:我们在 Java 中创建的这个线程,和操作系统底层的物理线程到底是什么关系?是一对一的,还是多对一的?

这个问题,往往是面试中区分“初级 CRUD 工程师”和“高级架构师”的一道经典分水岭。

今天,我们就来直接亮出底牌:在大家目前最常用的主流 Java 版本(如 JDK 8 到 JDK 17)中,你创建的 Java 线程与操作系统的底层物理线程是绝对的**一对一(1:1)**关系!

但这只是冰山一角。要想真正看透 Java 并发编程的底层逻辑,我们必须翻开 Java 线程模型演进的“前世、今生和未来”。这是一部非常精彩的进化史。


阶段一:前世(Java 1.1 时代)—— 多对一(M:1)的“绿色线程”

在极其古老的 Java 版本中,操作系统根本不知道 Java 有多线程这回事。

  • 怎么做的:JVM 在用户态(内存里)自己模拟了一大堆线程,这些被称为绿色线程(Green Threads)。成百上千个 Java 线程实际上只对应操作系统里的 1 个物理线程。
  • 致命缺陷:因为操作系统只给 JVM 分配了 1 个物理线程的调度“坑位”,一旦某个 Java 线程发生了 I/O 阻塞(比如读写文件、等待网络响应),操作系统会直接把这唯一的一个物理线程挂起。结果就是,整个 JVM 进程里的所有 Java 线程全军覆没,跟着一起卡死。更糟糕的是,这种模式根本无法利用多核 CPU 的并行计算性能。

结局:由于天然的性能缺陷,绿色线程很快就被官方彻底抛弃了。


阶段二:今生(Java 1.2 ~ Java 20)—— 一对一(1:1)的“内核线程”

痛定思痛后,Java 迎来了漫长的 1:1 时代,这也是我们现在每天都在用的模式。

  • 怎么做的:当你用 Java 代码写下new Thread().start()时,JVM 底层会直接调用操作系统的 API(例如 Linux 下的clone()系统调用)。操作系统会在内核里为你硬生生地创建一个真实的物理线程(Kernel Thread)
  • 谁来调度:此时 JVM 彻底当了甩手掌柜。Java 线程什么时候执行、被分配到哪个 CPU 核心上、什么时候被切走,全部交由底层的操作系统内核去全权调度。

优势与痛点并存:

  • 优势:完美利用了多核 CPU 的性能。一个 Java 线程阻塞了,操作系统会自动把 CPU 切给另一个线程,互不影响。
  • 痛点(极度沉重)
    • 太占内存:在 Linux 下,创建一个物理线程默认要分配 1MB 的栈内存。如果你敢在 Java 里同时创建 10 万个线程,内存瞬间就会被打爆,直接引发 OOM。
    • 切换太慢:操作系统在物理线程之间进行上下文切换(Context Switch)时,需要频繁在“用户态”和“内核态”之间穿梭,保存和恢复各种硬件寄存器,性能损耗极其严重。

阶段三:未来(Java 21 及以后)—— 多对多(M:N)的“虚拟线程”

1:1 模型虽然稳定,但实在太重了,根本应对不了现在动辄百万并发的互联网高吞吐场景(比如 Go 语言的协程 Goroutine 就凭借轻量级大杀四方)。于是,Java 官方憋出了一个大招:Project Loom(虚拟线程 Virtual Threads)

  • 怎么做的:Java 在 JDK 21 中正式引入了虚拟线程,将线程模型进化为 M 个虚拟线程映射到 N 个物理线程上(M:N)。
  • 极其恐怖的性能:虚拟线程完全由 JVM 在用户态管理,不再需要向操作系统申请物理线程。它的体积只有区区几百字节!你现在可以在一台普通的笔记本电脑上,轻松写个 for 循环同时启动 100 万个虚拟线程,内存连一丁点波澜都不会有。
  • 底层原理:当一个虚拟线程遇到网络阻塞等 I/O 操作时,JVM 会迅速把它从底层的物理线程(载体线程)上“拔”下来,把宝贵的 CPU 坑位让给其他需要计算的虚拟线程,实现了真正的“零阻塞浪费”。

总结:一个通俗的终极比喻

为了更直观地理解,我们可以打个比方:

1:1 内核线程(现在的 Java):就像每个乘客(Java 线程)都配了一辆专属的**出租车(物理线程)**和司机。好处是随时待命,坏处是马路(CPU)很容易堵死,而且买车成本极高。

M:N 虚拟线程(未来的 Java):就像是高铁。成千上万的乘客(虚拟线程)只需要很少的几节车厢(物理线程)就能高效运走,上下车(上下文切换)非常快。

正因为我们目前广泛使用的 Java 1:1 物理线程是极其昂贵的系统资源(创建和销毁极其耗时),所以我们在平时的业务代码中,绝对不能频繁地去new Thread(),而是必须使用“线程池(ThreadPool)”把它们圈养起来重复利用!

http://www.cnnetsun.cn/news/1574352.html

相关文章:

  • Vivado 2018.3 安装时,这几个勾选千万别乱点!省下20G硬盘空间的正确姿势
  • Umi-OCR:免费离线OCR工具,3分钟掌握高效文字识别技巧 [特殊字符]
  • 3步打造专属离线OCR方案:Umi-OCR插件完全配置指南
  • 从架构图到代码:南北向接口在微服务设计中的实战解析
  • 上位机软件开发实战:从数据采集到可视化的全流程解析
  • Factory Bot Rails 工厂验证器:如何确保你的工厂定义始终正确
  • OpenClaw安全警报:nanobot镜像操作权限最佳实践
  • 分布式光伏接入对配电网电压的影响分析
  • EagleEye DAMO-YOLO TinyNAS抗遮挡检测效果展示
  • NBFC高级配置技巧:温度阈值与风扇速度的完美平衡
  • GTE-Pro保姆级教学:从MTEB榜单理解GTE-Large语义能力边界
  • 终极指南:ufw-docker在AWS、GCP、Azure云环境中的完整部署方案 [特殊字符]
  • V2EX GAE 完全指南:如何在Google App Engine上部署现代化社区平台
  • Lenovo Legion Toolkit终极指南:轻松掌控联想游戏本性能
  • twitter-text测试驱动开发:使用Conformance测试确保解析一致性
  • Java车载CAN消息处理延迟超标?用LockSupport+无锁RingBuffer重构通信栈,端到端P99延迟压至1.2ms(含JFR火焰图对比)
  • 别再写死红绿灯时间了!基于STM32的智能调控核心代码解析与优化
  • Gazebo仿真避坑指南:手把手教你创建会移动的障碍物(附完整Python代码)
  • AI的正规方程法与梯度下降法的比较研究
  • Qwen3-VL-8B-Instruct保姆级部署教程:5分钟在MacBook上跑通多模态AI
  • 华为交换机VLAN间通信保姆级教程:从DHCP配置到静态路由全流程
  • 轻量化AI读脸术体验:不依赖PyTorch/TensorFlow,快速部署使用
  • Jupyter Notebook项目管理效率翻倍:自定义工作路径的3种实战方法(含CMD与Git Bash)
  • 3步找回QQ号:手机号逆向查询工具完全指南
  • Qwen3.5-4B-Claude模型算法竞赛刷题助手:LeetCode题目智能分析与解题
  • FLUX.1-dev问题解决:部署常见错误排查,让你一次跑通不踩坑
  • genshin-fps-unlock:突破原神帧率限制的完整解决方案
  • 游戏制作与项目管理完全手册:从概念到发布的完整流程
  • 深入SQLite JDBC核心架构:揭秘NativeDB与JNI层的工作原理
  • 无需3D基础!Face3D.ai Pro从安装到生成完整教学