Skip to content

从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 线程(可选)

上次更新于: