从js的角度来讲线程和进程的关系
简单来讲:进程包含多个线程,线程是进程的最小单位。形象点就是进程是一条马路,而线程就像跑在马路上一辆辆的小汽车。
从 JavaScript 的角度理解「进程(Process)」和「线程(Thread)」,可以抓住一句核心话:
JS 本身是单线程的,但 JS 运行环境是多进程 / 多线程的。
下面我用前端 / Node.js 都能对得上号的视角,一步一步拆开讲。
一、先给一句“JS 版定义”
1️⃣ 进程(Process)
进程 = 一个独立的运行环境
- 有 独立内存空间
- 一个进程挂了,不影响其他进程
- 操作系统分配资源的最小单位
在 JS 世界里:
- 一个浏览器 Tab
- 一个 Node.js 程序(
node index.js)
通常就是 一个进程
2️⃣ 线程(Thread)
线程 = 进程里干活的执行单元
- 共享进程内存
- 线程切换比进程快
- CPU 实际调度的是线程
在 JS 世界里:
- JS 主线程
- 事件循环线程
- 渲染线程 / IO 线程 / Worker 线程
二、关键结论(记住这 3 条就够了)
1. JS 执行是「单线程」
js
console.log(1);
while (true) {}
console.log(2); // 永远执行不到同一时刻:
- 只能执行 一段 JS 代码
- 不存在多个 JS 同时跑在一个线程里
2. JS 的运行环境是「多线程」
虽然 JS 代码只有一个主线程执行,但:
- 定时器
- 网络请求
- 文件 IO
- DOM 渲染
并不是 JS 主线程在干
3. JS 通过「事件循环」用单线程“调度”多线程结果
text
┌──────── JS 主线程 ────────┐
│ 执行同步代码 │
│ 执行微任务 (Promise) │
│ 执行宏任务 (setTimeout) │
└───────────────────────────┘三、浏览器里的「进程 & 线程」(非常重要)
浏览器是多进程架构
常见的(简化):
| 进程 | 作用 |
|---|---|
| Browser 进程 | 地址栏、书签、UI |
| Renderer 进程 | JS、DOM、CSS、渲染 |
| GPU 进程 | 图形加速 |
| Network 进程 | 网络请求 |
一个 Tab ≈ 一个 Renderer 进程
Renderer 进程里有什么线程?
| 线程 | 干什么 |
|---|---|
| JS 主线程 | 执行 JS |
| GUI 渲染线程 | 绘制页面 |
| 事件触发线程 | 用户输入 |
| 定时器线程 | setTimeout |
| 异步请求线程 | fetch / XHR |
JS 主线程 & 渲染线程互斥
- JS 执行 → 页面不能渲染
- 页面渲染 → JS 暂停
这就是为什么 长 JS 会卡页面
四、Node.js 中的进程 & 线程
Node.js = 单进程 + 多线程(底层)
1️⃣ 表面上
js
node index.js一个 Node 进程
一个 JS 主线程
2️⃣ 底层真实情况(libuv)
Node 内部有一个 线程池(默认 4 个):
| 类型 | 谁在干 |
|---|---|
| JS 执行 | 主线程 |
| 文件 IO | 线程池 |
| DNS | 线程池 |
| 压缩 / 加密 | 线程池 |
js
fs.readFile("a.txt", () => {
console.log("done");
});readFile 不阻塞 JS
IO 在线程池
回调回到 JS 主线程
五、Worker:JS 世界里的“真多线程”
1️⃣ Web Worker(浏览器)
js
const worker = new Worker("worker.js");每个 Worker:
- 独立线程
- 独立 JS 执行环境
不能操作 DOM
通过
postMessage通信
本质:
一个进程里,多个 JS 线程
2️⃣ Worker Threads(Node.js)
js
const { Worker } = require("worker_threads");- 真·多线程 JS
- 适合 CPU 密集型任务
- 和浏览器 Worker 概念一致
六、一张「JS 视角」的终极关系图
text
操作系统
└─ 进程(Browser / Node)
├─ JS 主线程(单线程执行)
├─ IO / 定时器 / 网络线程
├─ 事件循环
└─ Worker 线程(可选)